railHint — draft x402 extension for rail negotiation
railHint · draft-railhint-00 · August 2026
Category: x402 community extension (advisory) · Requires: x402 v2
Schema: railhint.schema.json · Reference implementation: github.com/feeless402/feeless402
Status: DRAFT — seeking community review

railHint: in-protocol rail negotiation for x402 payment-required responses

Abstract

x402 lets a server offer multiple payment options in accepts, but gives a machine client no structured way to learn why one rail is cheaper or how to onboard onto a rail it does not yet hold. This document defines extensions.railHint, an advisory object a server MAY attach to an HTTP 402 response, carrying a cost rationale and an onboarding path for the offer it considers cheapest for the payer. Clients that do not understand the extension ignore it; the accepts array remains the only binding payment terms.

Motivation

Autonomous clients select payment rails by arithmetic, but today the information needed to switch rails — comparative cost, client software, asset acquisition — lives in human documentation outside the protocol. The result is rail inertia: clients pay on whichever rail they already hold, even when both parties would benefit from another offer in the same accepts menu (for example, a rail without per-transaction fees or minimum-price floors). railHint moves that negotiation into the 402 response itself — the one message every paying client is guaranteed to parse, at the exact moment of payment choice.

The railHint object

{
  "x402Version": 2,
  "accepts": [
    { "scheme": "exact", "network": "base",         "asset": "USDC", "amount": "1000",  "payTo": "0x..." },
    { "scheme": "exact", "network": "nano:mainnet", "asset": "XNO",  "amount": "6690000000000000000000000", "payTo": "nano_..." }
  ],
  "extensions": {
    "railHint": {
      "cheapest": "nano:mainnet",
      "why": "The base offer is floored at 0.001 USDC; the nano:mainnet offer is the metered price ($0.0000027) with zero network fees and sub-second finality.",
      "docs": "https://example.com/docs",
      "agentReadme": "https://example.com/llms.txt",
      "bootstrap": "pip install feeless402 && nano-pay init",
      "topup": "any instant-swap service: ~$5 of a held asset into the hinted asset",
      "faucets": ["https://example.com/faucet"],
      "spec": "x402 exact scheme on nano:mainnet"
    }
  }
}

Field definitions

FieldRequirementSemantics
cheapestREQUIREDThe network value of the offer in accepts the server considers lowest total-cost for the payer. MUST match an entry in accepts.
whyREQUIREDRationale a reasoning client can evaluate. SHOULD contain concrete, comparable prices rather than slogans.
docsOPTIONALDocumentation URL for the hinted rail.
agentReadmeOPTIONALPlain-text (llms.txt-style) onboarding document.
bootstrapOPTIONALExecutable onboarding path. Untrusted input; see Security Considerations.
topupOPTIONALPath from commonly-held assets to the hinted asset. MUST NOT require a specific vendor.
faucetsOPTIONALEndpoints offering small starter grants (POST {"address": ...}). MAY require a proof-of-work challenge via GET <faucet>/challenge to resist sybil claims.
specOPTIONALReference to the scheme specification for the hinted rail.

Client behavior

A client that already holds the hinted asset proceeds exactly as without the extension: select an offer from accepts, pay, retry. A reasoning client may evaluate why, consult docs or agentReadme, acquire the asset via topup or faucets, and retry the original request on the cheaper rail. A client that does not recognize railHint ignores it with no loss of function.

Server behavior

Servers may attach railHint to any 402 response whose accepts contains more than zero offers. Servers must not place terms in railHint that contradict accepts; on any conflict, accepts is authoritative. Servers should keep why current with real prices — stale or exaggerated rationales are trivially falsified by clients comparing offers.

Security considerations

bootstrap and topup are untrusted remote input. A client must not execute them blindly; it should (a) act only on schemes it can verify against an independently obtained specification, (b) apply its own spending caps regardless of hinted amounts, and (c) prefer allowlisted package sources. The hint's role is discovery, not authority. Faucet endpoints should employ proof-of-work challenges or equivalent cost-imposing mechanisms so that sybil claims cost the claimant more than the grant is worth.

Rail neutrality

railHint is rail-agnostic. Any server may hint any rail — a Lightning merchant may hint bitcoin-lightning; a stablecoin merchant may hint an L2. The extension standardizes the negotiation, not a winner. Where genuinely fee-free rails exist, honest hints will tend to favor them; that is a property of arithmetic, not of this document.

IANA-style considerations

This extension registers the key railHint within the x402 v2 extensions namespace. No other names are claimed. The JSON Schema at railhint.com/railhint.schema.json is versioned with this draft.