Payment schemes
The two ways a pay-kit Go gate charges — fixed charge and metered usage (upto) — plus where MPP session lives.
A gate's Kind decides how it charges, and which middleware you mount. The default is a fixed charge; usage is a separate Kind gated with RequireUsage.
| Scheme | Gate | Middleware | What it does |
|---|---|---|---|
| Fixed charge | GateFixed (default) | client.Require(gate) | Charge a fixed amount once, settled before the handler runs. |
| Metered usage | GateUsage | client.RequireUsage(gate) | Authorize a ceiling, meter actual usage, settle the real amount and refund the rest. |
Usage gates settle a handler-determined amount via x402 upto, so they are x402-only and cannot carry fees, and
the operator must have a signer. MPP session ships in Go but at the protocol layer
(protocols/mpp/server.NewSession + SessionMiddleware), not as a paykit.Gate; subscription and x402
batch-settlement are not implemented in Go.
Fixed charge
The default gate: a fixed price the client settles over MPP or x402 (its choice). Settlement runs before your handler.
client, err := paykit.New(paykit.Config{ Network: paykit.SolanaLocalnet, Accept: []paykit.Protocol{paykit.X402, paykit.MPP}, MPP: paykit.MPPConfig{ Realm: "MyApp", ChallengeBindingSecret: []byte("local-dev-secret"), },})if err != nil { panic(err)}gate := paykit.Gate{Amount: paykit.MustParseUSD("0.01"), Desc: "Stock quote"}// client.Require(gate) is func(http.Handler) http.Handler — it settles the// 402 (MPP or x402, the client's choice) before your handler runs.mux := http.NewServeMux()mux.Handle("/quote", client.Require(gate)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { pmt, _ := paykit.PaymentFrom(r.Context()) fmt.Fprintf(w, `{"ok":true,"paid_via":%q}`, pmt.Protocol)})))The client side is a single call through the paying transport — see Client:
// The returned *http.Client settles a 402 transparently on any call.httpClient := x402client.NewClient(signer, rpc)resp, err := httpClient.Get("https://api.example.com/quote")if err != nil { panic(err)}defer resp.Body.Close()body, _ := io.ReadAll(resp.Body)fmt.Println(string(body))Metered usage (upto)
A GateUsage gate advertises Amount as the ceiling. The client opens a payment channel depositing that maximum; the handler meters real usage and reports it through the Charge meter from paykit.ChargeFrom; the gate settles the actual amount and refunds the remainder after the handler returns. This is the shape for LLM-token billing or per-byte metering.
// A usage gate advertises Amount as the authorized ceiling; the handler// reports actual consumption and the gate settles that, refunding the rest.gate := paykit.Gate{ Amount: paykit.MustParseUSD("1.00"), Desc: "Summarize, billed per token", Kind: paykit.GateUsage, // x402 upto; usage gates are x402-only}mux := http.NewServeMux()mux.Handle("/summarize", client.RequireUsage(gate)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Meter actual usage in base units; the gate settles it (clamped to the // ceiling) after the handler returns. if charge, ok := paykit.ChargeFrom(r.Context()); ok { charge.Charge(50_000) // 0.05 USDC } w.Write([]byte(`{"summary":"..."}`))})))