Leash operates two public facilitators: https://facilitator.leash.market (mainnet) and https://devnet-facilitator.leash.market (devnet). These are the SDK defaults. Anyone can self-host the same binary — useful for local dev, integration tests, or running on a custom settlement key.

Default facilitators vs overrides (any compatible host)

Leash SDKs (@leash/buyer-kit, @leash/seller-kit) resolve the facilitator URL through defaultFacilitatorFor: optional LEASH_FACILITATOR_URL, else a per-network default, else a universal fallback. The table below is the “what you get if you set nothing” default — it is not a whitelist. You can point LEASH_FACILITATOR_URL (or facilitator: on createBuyer / createSeller) at any HTTPS base URL that implements the x402 facilitator HTTP API and publishes the exact SVM scheme for your cluster.
NetworkDefaultExample third-party alternatives
Devnethttps://devnet-facilitator.leash.markethttps://devnet-facilitator.leash.market, http://localhost:8787 (local @leash/facilitator-app)
Mainnethttps://facilitator.leash.markethttps://facilitator.leash.market, or any other mainnet-capable x402 facilitator you run or trust
The hosted Leash API (api.leash.market) uses LEASH_API_FACILITATOR_URL for its own /x/{id} paywall and seller-utils — that is server-side only and does not change your SDK defaults. That value can also be any compatible facilitator base URL, not only the Leash binary. The web playground reads NEXT_PUBLIC_LEASH_FACILITATOR_URL (client) and LEASH_FACILITATOR_URL (server routes). See Create a payment link — Facilitator.

What a facilitator does

In x402, the buyer signs a transaction transferring tokens to the seller. The buyer never touches the blockchain — instead, the seller forwards the signed payload to a facilitator:
  1. POST /verify — facilitator inspects the signed transaction and confirms it does what the seller asked (right amount, right mint, right destination, right network).
  2. POST /settle — facilitator adds its own signature as fee payer, broadcasts to Solana, and returns the on-chain signature.
  3. GET /supported — published list of (scheme, network) tuples the facilitator accepts. HTTPFacilitatorClient calls this on startup.
The facilitator absorbs the fee-payer SOL cost so buyers can pay in USDC alone. That’s the entire deal — the rest is wire format and key management.

Wire compatibility

@leash/facilitator registers the Exact SVM scheme from @x402/svm for both protocol v1 and v2. That means every existing Leash buyer (@leash/buyer-kit) and seller (@leash/seller-kit) deployment works out of the box: just set LEASH_FACILITATOR_URL.
# Use the Leash devnet facilitator (default; no config needed)
export LEASH_FACILITATOR_URL=https://devnet-facilitator.leash.market

# Or point at a local self-hosted instance
export LEASH_FACILITATOR_URL=http://localhost:8787
The endpoint shape exactly matches HTTPFacilitatorClient from @x402/core, so dropping in any other facilitator URL (svmacc, PayAI, Coinbase) is a one-env-var swap.

Self-host in 5 commands

# 1. Install the package binary
pnpm add -g @leash/facilitator

# 2. Generate a Solana keypair to act as fee payer
solana-keygen new -o .leash-fee-payer.json --no-bip39-passphrase

# 3. Top it up on devnet (free)
solana airdrop 1 -k .leash-fee-payer.json --url https://api.devnet.solana.com

# 4. Export the secret
export LEASH_FACILITATOR_SECRET_KEY="$(cat .leash-fee-payer.json)"

# 5. Boot the server
leash-facilitator
Output:
[leash-facilitator] listening on http://0.0.0.0:8787
[leash-facilitator] networks: solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1
[leash-facilitator] fee payer(s): HxzEv...
That’s a real x402 facilitator running on devnet. Verify it from another terminal:
curl http://localhost:8787/supported | jq
You should see one entry per (scheme, network, x402Version) tuple.

Running inside the monorepo

For local hacking on the facilitator itself, use the workspace app:
solana-keygen new -o .leash-fee-payer.json --no-bip39-passphrase
solana airdrop 1 -k .leash-fee-payer.json --url https://api.devnet.solana.com
export LEASH_FACILITATOR_SECRET_KEY="$(cat .leash-fee-payer.json)"
pnpm --filter @leash/facilitator-app dev
Then in a second terminal:
export LEASH_FACILITATOR_URL=http://localhost:8787
pnpm --filter @leash/buyer-demo start    # all three demos pick this up
pnpm --filter @leash/seller-demo start
pnpm --filter @leash/merged-demo start

Configuration

Env varDefaultDescription
LEASH_FACILITATOR_SECRET_KEYrequiredSolana 64-byte secret. Either a JSON byte array (Solana CLI export) or a base58 string (Phantom/Solflare export).
LEASH_FACILITATOR_NETWORKSdevnetComma list. Allowed: devnet, testnet, mainnet.
LEASH_FACILITATOR_PORT8787HTTP port.
LEASH_FACILITATOR_HOST0.0.0.0Bind address.
LEASH_FACILITATOR_RPC_URLkit defaultsOverride the RPC URL used for ALL networks.
LEASH_FEE_BPS100Protocol fee rate in basis points (100 = 1.00%). Set to 0 to disable the fee leg entirely.
LEASH_FEE_ENFORCEenforceenforce rejects bad/missing fee legs. warn logs them but still settles. off skips fee verification (vanilla x402).
LEASH_FEE_AUTHORITY_MAINNET3DdcJkvjW7KLtMeko3Zr57jEJWhqRHuPsEBFm1XJYh7WPubkey that receives the mainnet fee leg. Override only if running your own facilitator with your own treasury.
LEASH_FEE_AUTHORITY_DEVNET3DdcJkvjW7KLtMeko3Zr57jEJWhqRHuPsEBFm1XJYh7WSame, for devnet.
The Leash protocol fee block is published on /health:
$ curl -sS http://localhost:8787/health | jq .protocol_fee
{
  "bps": 100,
  "enforcement": "enforce",
  "authority": "3DdcJkvjW7KLtMeko3Zr57jEJWhqRHuPsEBFm1XJYh7W"
}
Buyer SDKs poll this on boot and refuse to settle if their locally computed feeAuthority disagrees with what the facilitator publishes. See Protocol fee for the full wire shape, math worked examples, and self-host guidance.

Going to mainnet

The codepath supports it; v0.1 of the hosted instance does not. To run your own mainnet facilitator:
  1. Generate a fresh keypair (do not reuse the devnet one).
  2. Fund it with real SOL — facilitators pay tx fees out of pocket. Roughly 0.0001 SOL per settlement; 0.1 SOL is a comfortable runway for thousands of payments.
  3. LEASH_FACILITATOR_NETWORKS=mainnet (or devnet,mainnet).
  4. Front the HTTP listener with TLS + abuse protection (Cloudflare Worker / nginx). The package itself does not implement auth or rate limiting; the assumption is you’ll terminate that at the edge.
The CLI prints a WARNING line when mainnet is enabled. Heed it.

Architecture (one paragraph)

@leash/facilitator is a thin Hono app built on x402Facilitator from @x402/core. Instead of registering the upstream ExactSvmScheme / ExactSvmSchemeV1 directly, it registers LeashExactSvmFacilitator (x402 v2) and LeashExactSvmFacilitatorV1 (legacy v1) — two custom schemes that extend the upstream verification with: optional leading CreateAssociatedTokenAccountIdempotent instructions (validated and paid for by the facilitator), the 1% Leash protocol fee leg enforcement, and a final RPC simulation gate. Settlement co-signs as fee payer and broadcasts via the unmodified upstream path. Leash-specific extras: env-driven config (LEASH_FACILITATOR_* + LEASH_FEE_*), a base58 secret-key decoder so you can paste a Phantom export verbatim, and a /health endpoint reporting the fee-payer address and live protocol_fee block.

Roadmap

  • v0.2 — Settlement persistence. Cross-reference settled txs with ReceiptV1 records from @leash/runner to power the explorer.
  • v0.3 — Multi-key fee payer rotation for higher throughput.
  • v0.4 — Mainnet on the hosted instance.
  • v0.5 — Hooks for fraud detection and per-merchant rate limiting.
If you self-host today on mainnet, you’re already getting v0.4 — just without the conveniences of the hosted instance.