pay.sh docs
SDKPython

Pricing

Price a route in solana_pay_kit — typed USD amounts, the Gate.build DSL, a Pricing registry, fee splits, and dynamic per-request pricing.

A gate is a frozen value object built with Gate.build: an amount, an ordered list of accepted protocols, and zero or more named fees. The amount is a Price from usd(...).

Amounts

from solana_pay_kit import usd, Stablecoin

usd("0.10")                              # $0.10, default settlement (USDC)
usd("0.10", Stablecoin.USDC, Stablecoin.PYUSD)  # narrow/order the settlement assets

The Gate DSL

from solana_pay_kit import Gate, Protocol, usd

# Simple. Customer pays $0.10, pay_to nets $0.10.
Gate.build(name="report", amount=usd("0.10"), description="Premium report")

# x402-only.
Gate.build(name="api_call", amount=usd("0.001"), accept=(Protocol.X402,))

# Stripe-Connect "application fee": customer pays $10.00, SELLER nets $9.70,
# PLATFORM nets $0.30. x402 auto-disabled (fees need MPP).
Gate.build(name="marketplace_sale", amount=usd("10.00"),
           pay_to=SELLER, fee_within={PLATFORM: usd("0.30")})

# Surcharge: customer pays $10.50, SELLER nets $10.00, PLATFORM nets $0.50.
Gate.build(name="ticket", amount=usd("10.00"),
           pay_to=SELLER, fee_on_top={PLATFORM: usd("0.50")})

fee_within carves a fee out of the amount (the recipient nets less); fee_on_top adds a surcharge on top (the customer pays more, the recipient nets full).

Registry and inline

Lift multiple gates into a Pricing subclass and reference them by name, or pass a bare price for a one-off:

from solana_pay_kit import Pricing

class Catalog(Pricing):
    def __init__(self):
        defaults = {"default_pay_to": solana_pay_kit.config().effective_recipient()}
        self.report = Gate.build(name="report", amount=usd("0.10"), **defaults)

catalog = Catalog()

@app.get("/report")
@require_payment("report", pricing=catalog)
def report(): ...

# Inline: skip the registry, pass a price directly.
@app.get("/oneoff")
@require_payment(usd("0.25"))
def oneoff(): ...

Dynamic pricing

@gate("tiered")
def tiered(request):
    return usd("5.00") if request.args.get("tier") == "premium" else usd("0.10")

Boot-time validations raise ConfigurationError (or a subclass): pay_to is required, a fee recipient must differ from pay_to, fees share one denomination with the amount, sum(fee_within) <= amount, and a fee-bearing gate cannot be accept=(Protocol.X402,) (raises ProtocolIncompatibleError).

On this page