On-Behalf-Of, no inter-account
transfers.
This is the right starting point if you operate one storefront, one
treasury, one consolidated ledger.
Mental model
When this fits
- One product, one storefront, one treasury.
- You don’t need per-customer balance isolation in SkinShark.
- All reconciliation can happen at one merchant level.
- Operations is a single team, not multi-tenant.
Endpoints you’ll use
All sub-user-context routes work without anOn-Behalf-Of header — they
run as the merchant. So you only ever need:
Skip these (for now)
These endpoints are real, just not relevant in Core API mode:/merchant/users/*— sub-user CRUD and funding/merchant/users/{id}/wallet— sub-user wallet readsOn-Behalf-Ofheader — never needed
Daily operation
A typical day in Core API:1
User browses
Your frontend calls
GET /market/search and GET /market/items/{itemId}/listings
to render inventory.2
User buys
POST /market/buy debits your merchant wallet by totalPrice and
creates a trade.3
Server confirms
A
trade.completed webhook fires (or your WebSocket subscriber sees
trade.completed). Persist the trade against your own order table by
externalId.4
Reconcile
Nightly job calls
GET /merchant/ledger?type=spot and GET /merchant/stats
against yesterday’s window for accounting.5
Top up
When the merchant balance dips, deposit via Gate Pay / on-ramp /
crypto. The deposit credits the merchant wallet directly.
Cancelling an order
tradeRef is the trade id or the externalId you sent. itemRef is TradeItem.id or the
per-item externalId you sent — set one on every item you might want to cancel later:
initiated or pending, once the order reached the supplier,
and no earlier than 30 minutes after creation — before that you get TRADE_CANCEL_TOO_SOON
with cancellableAt. Anything already delivered or in flight to Steam is TRADE_NOT_CANCELLABLE.
Both are best-effort. The trade-level call returns 200 even when some items are refused, with
a per-item status and reason, so check the body rather than the status code. A successful
cancel refunds in full with no penalty, and the money arrives asynchronously via
trade.refunded — the response only confirms the supplier accepted.
Code template
What you give up
- No tenant isolation. All trades show up under one merchant. If a customer disputes, they’re not separable in SkinShark’s view.
- One ledger. Per-customer accounting is your job, not SkinShark’s.
- Migration cost later. If your business needs per-customer wallets,
you’ll move to Full Platform — usually a one-time refactor where you
swap one
api()call signature to take a sub-user ID.
When to graduate
Move to Full Platform when you need:- Per-customer balance isolation (chargeback containment, audit clarity).
- Multi-tenant reporting in the merchant dashboard.
- Per-customer fee overrides.
- Self-service crypto deposits per customer.
On-Behalf-Of, route customer-attributable calls there. The catalog
and trade primitives don’t change.