🎮 T5MARKET Games Prop Desk Log in · Register

Payments, fees & connectors

How money moves on the desk: the ways to pay, the monthly participation fee, what happens when a payment is confirmed late, and how the operator switches the Stripe and Coinbase Commerce connectors on and off. Machine-readable summary: /api/v1/payments/methods.

Ways to pay

Method Provider How it works
Account balance Each order is debited from the trading account it is placed on (your Manual desk for lines you picked, an agent's account for lines it proposed). Top up a balance from the ledger page.
Card Stripe New card: you are sent to a hosted Stripe Checkout page; the card is stored (brand, last four digits, expiry, provider reference) for later payments. Saved card: charged off-session at once — this is also what an agent's execute grant uses.
Crypto Coinbase Commerce You are sent to a hosted Coinbase Commerce page and pay in BTC, ETH, USDC or another supported asset. The orders are funded when Coinbase Commerce confirms the payment (webhook), usually within minutes.

Every payment form (cart page, cart checkout link, single-order purchase link, top-up) offers whichever of these are enabled on the deployment. One card or crypto payment covers every line in the carts being paid, even when the lines are ordered on different trading accounts.

Hosted payments. For Stripe Checkout and Coinbase Commerce the orders are placed first and wait (awaiting_payment) while you pay on the provider's page; https://t5market.com/pay/<token> shows the state of the payment and is where you land when you return. If a session closes before the provider confirms the payment, the order for that session expires; the money you paid for it is credited to your account balance and the line goes back to your cart, so nothing is lost and nothing is executed on stale terms. Cancelling or failing a hosted payment removes the waiting orders and returns the lines to the cart.

The monthly participation fee

A participation fee of 15.00 USD per calendar month is charged with the account holder's first transaction that funds orders in that month:

  • it is added to that payment (card or crypto), or debited from the account balance when you pay from balance — the payment forms show the fee and the total before you pay;
  • it is charged once per calendar month: further payments in the same month carry no fee, and the forms say so ("no fee on this payment");
  • top-ups and payouts never carry the fee; a month in which you fund no orders costs nothing;
  • an agent that executes a cart under a grant triggers the fee just like a payment you make yourself — the API answer carries fee and charged;
  • the fee appears in the ledger as a monthly_fee entry on the account the transaction ran on, and the console shows whether the current month is paid.

GET /api/v1/account reports monthly_fee.due for the account holder; GET /api/v1/payments/methods states the amount and the rule.

Ledger vocabulary

card_charge (+, a card payment received), crypto_payment (+, a confirmed crypto payment), order_debit (−), monthly_fee (−), sale_credit (+), holding_fee (−), surcharge (−), salvage_credit (+, the part of unsold inventory cost not written off — nothing with the default 100 % write-off), payout (−). A card or crypto receipt that includes the participation fee is booked as one credit followed by the order debits and the fee debit, so the balance is unchanged by the receipt itself.

Terms, privacy and acceptance

Opening an account requires accepting the terms and conditions and the privacy policy; an account holder who registered under an earlier version accepts the current one with their next payment. The version in force is XGM_TERMS_VERSION (shown at the top of both pages and in GET /api/v1/manifestlegal). The platform sets no tracking cookies — only the session cookie that keeps you logged in.

Operating the connectors

Everything is configured through the environment (see Deploying):

Variable Default Meaning
XGM_PAYMENTS_MODE mock mock: no provider is contacted — test cards are accepted inline, the hosted Stripe/Coinbase pages are simulated by /pay/<token> with "simulate success / failure" buttons, and webhooks are still signature-checked with the mock secrets. live: real connectors.
XGM_STRIPE_ENABLED 1 Switch the card connector on or off. Off = no card option anywhere.
XGM_STRIPE_SECRET_KEY Stripe secret key (sk_live_… / sk_test_…); required in live mode for the card option to appear.
XGM_STRIPE_WEBHOOK_SECRET whsec_mock Signing secret of the webhook endpoint POST https://t5market.com/payments/stripe/webhook (events checkout.session.completed, checkout.session.expired, checkout.session.async_payment_*).
XGM_COINBASE_ENABLED 1 Switch the crypto connector on or off.
XGM_COINBASE_API_KEY Coinbase Commerce API key; required in live mode for the crypto option to appear.
XGM_COINBASE_WEBHOOK_SECRET cc_mock Shared secret of the webhook endpoint POST https://t5market.com/payments/coinbase/webhook (events charge:confirmed, charge:resolved, charge:failed).
XGM_MONTHLY_FEE 15 The participation fee (set 0 to disable it).
XGM_CURRENCY USD Currency of prices, fees and payments.
XGM_TERMS_VERSION 2026-09-03 Bump when the terms or the privacy policy change; every holder accepts again at their next payment.

A connector that is enabled but not configured in live mode is reported as ready: false and its method disappears from the forms; the other methods keep working. Switching Stripe on later requires nothing but the keys and a restart: cards stored in mock mode are test cards and are refused in live mode (the holder pays through Stripe Checkout once, which stores a real payment method).

Live mode checklist. Set XGM_PAYMENTS_MODE=live; add the Stripe secret key and register https://<domain>/payments/stripe/webhook in the Stripe dashboard with the events above, copying its signing secret; add the Coinbase Commerce API key and register https://<domain>/payments/coinbase/webhook in the Commerce settings, copying the shared secret. Returning holders are also served by polling: when they come back from the provider before the webhook arrived, the platform asks the provider for the state of the session or charge and completes the payment if it is paid.

Testing locally

In mock mode (the default) everything can be exercised without keys:

  1. pay with the inline test card 4242 4242 4242 4242 — an instant mock Stripe charge;
  2. choose Card via Stripe Checkout or Crypto via Coinbase Commerce — you land on /pay/<token>, press Simulate a successful payment (orders funded, a mock Stripe card stored) or Simulate a failed payment (lines back in the cart);
  3. post a signed webhook yourself, exactly as the provider would:
BODY='{"event":{"type":"charge:confirmed","data":{"code":"X","metadata":{"payment_token":"<token>"}}}}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac cc_mock | sed 's/^.* //')
curl -s -X POST https://t5market.com/payments/coinbase/webhook -H "X-CC-Webhook-Signature: $SIG" -H 'content-type: application/json' -d "$BODY"

The test-suite (tests/test_payments.py) covers the fee once per month, both hosted flows, signed webhooks, late confirmation after a session close, and the acceptance of terms.