Skip to main content
Let players choose skins and deposit their accepted value into your own balance system. Your server creates the session and credits the player after verified completion. The hosted checkout uses the normal Skinloop design and shows a Balance total, without order overpayment or a standing limits block. This is separate from store-order checkout. It does not provide a player wallet, betting engine, withdrawals or instant credit against protected CS2 trades. Existing store integrations and payment.* webhooks stay unchanged.

Required setup

  1. Use an active Skinloop merchant account and a server-side API key with deposits:create and deposits:read. Enable Rust, CS2 or both on that key.
  2. In Webhooks, create an HTTPS endpoint and select Also receive player deposit events. Completion and reversal subscriptions are required before creating sessions. Keep the signing secret on your server.
  3. Add your return domain to the allowed checkout origins under API & Webhooks. Use your own authenticated player ID, not a player ID supplied unchecked by the browser.
Never place a merchant API key, signing secret, player email or private account data in the hosted URL.

Request body

POST /v1/merchant-api/deposit-sessions

Example request

All amounts are integer USD cents. This example allows $5 to $500. Provider eligibility and availability still apply; it does not promise that every item or amount is accepted. Store the returned id, creditReference, merchantReference and playerReference in your database before opening hostedUrl. Retry the same request with the same idempotency key if the network response is lost. A changed request with that key, or a reused merchant reference for another session, is rejected. Session expiry is 30 minutes by default, configurable from 5 minutes to 24 hours. It limits starting a deposit, not settlement of a trade already opened.

Valuation and checkout

The player chooses skins first. Skinloop issues a short-lived server valuation, valid for at most two minutes and never past the session expiry. Confirmation checks the exact items, game, current prices and inclusive limits again. Expired valuations and changed prices require refreshing the inventory and confirming the current selection. A browser cannot set the accepted amount, switch the receiving merchant, change the player reference or attach a second trade to the same session. Once a trade has been reserved, an idempotent retry returns that original trade and accepted value. It does not reprice an existing deposit or create a replacement trade.

States and spendable credit

Rust is not credited merely because a trade was created. CS2 remains pending during protection. A countdown ending, a success redirect or a screenshot is never payment confirmation. Instant spendable credit against a CS2 hold is not part of this product.

Signed notifications

Player deposits emit only these dedicated events:
  • deposit.pending, including a transition into hold.
  • deposit.completed.
  • deposit.failed, with a reason such as canceled or declined.
  • deposit.reverted.
They use the existing webhook signing and retry mechanism. Verify the signature against the raw request body using your endpoint secret. Deliveries retry when your receiver is unavailable, up to the configured retry limit; exhausted deliveries remain available for investigation and replay. Treat delivery as at least once, not exactly once and not necessarily ordered. Example event:
The event ID identifies a notification. creditReference identifies the one player deposit, including retries and any later reversal. The actual accepted value is the amount to reconcile, not the session minimum or maximum.

Status lookup

Credit the player once

Your receiver must:
  1. Verify the webhook signature and identify the saved deposit belonging to your merchant.
  2. Read the authenticated session status for recovery or out-of-order delivery. On lookup failure, retry later; do not assume success.
  3. In one database transaction, lock your deposit record and verify the stored player reference, currency and accepted amount.
  4. Credit only for current completed status and canCreditPlayer: true. Enforce a unique constraint on creditReference and insert the credit and balance change atomically.
  5. Track event IDs and sequence numbers so duplicate or older notifications cannot restore an outdated state. A reversal needs its own unique compensating entry, not deletion of the original credit. If the deposit was never credited, a reversal must not debit the player.
  6. Acknowledge only after durable processing, or after durably queuing the event for your own worker.
Do not use the product-order receiver to credit players or fulfill a store order from a deposit.* event. Skinloop prevents duplicate trade creation and emits durable, unique events. Your server must enforce the single credit in the player ledger it controls. The public checkout projection omits player and merchant references. Keep the authenticated recovery response on your server.