| Internet-Draft | FADP | April 2026 |
| Ganji | Expires 23 October 2026 | [Page] |
This document defines the Fluid Agentic DeFi Protocol (FADP), version 1.0. FADP is an application-layer protocol layered atop HTTP that enables autonomous AI agents to pay for access to web resources using on-chain cryptocurrency transfers, with cryptographic proof of payment embedded directly in HTTP headers.¶
FADP extends HTTP 402 (Payment Required) with two new header fields:
X-FADP-Required, which a server uses to communicate payment
terms to an agent, and X-FADP-Proof, which an agent uses to
supply a verifiable on-chain payment receipt. A nonce-challenge
mechanism prevents proof replay. An optional verification endpoint
allows third-party on-chain confirmation without requiring the verifying
party to run blockchain infrastructure.¶
FADP is designed for agent-to-server and agent-to-agent payment flows operating at sub-dollar granularity (micropayments), where credit-card or OAuth-based billing is impractical. The reference implementation targets USDC on Base (an Ethereum Layer 2), though the protocol is token- and chain-agnostic.¶
This note is to be removed before publishing as an RFC.¶
This document is submitted as an independent submission to the IETF datatracker. It does not represent the consensus of any IETF working group. The author welcomes discussion on the GitHub repository and via the contact address above.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 23 October 2026.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document.¶
Autonomous AI agents—software processes that browse the web, call APIs, and complete tasks on behalf of users without per-action human approval—are an emerging class of HTTP client. Unlike human-operated browsers, these agents cannot authenticate themselves to paid services via credit-card billing flows, OAuth consent screens, or similar interactive mechanisms. The practical result is that most commercial APIs are inaccessible to fully autonomous agents, forcing developers to hard-code credentials that cannot be scoped, limited, or revoked per-task.¶
HTTP has carried a 402 (Payment Required) status code since RFC 7231 [RFC7231], but that specification explicitly reserved the code for future use and defined no standard payment handshake. Numerous proprietary schemes have since emerged, but none has achieved broad adoption, and none addresses the specific needs of machine-to-machine micropayments at the scale and frequency that autonomous agents require.¶
Blockchain-based stablecoins—particularly USDC on high-throughput, low-cost Layer 2 networks—have made sub-cent on-chain transfers economically viable for the first time. A transaction settling 0.001 USDC (one-tenth of one cent) on Base costs roughly USD 0.0001 in gas, making per-request billing at very fine granularity practical.¶
FADP defines a minimal, HTTP-native handshake that combines these two properties: the well-understood 402 status code as a payment prompt, and an on-chain transfer as the payment instrument. The protocol requires no browser, no OAuth server, no API-key issuance flow, and no pre-existing billing relationship between the agent and the server. An agent that has a funded wallet and a Fluid agent key can pay for any FADP-gated resource it discovers, at runtime, without human intervention—provided the requested amount is within the agent's pre-configured spending limit.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
X-FADP-Required header
that specifies the payment terms the agent must satisfy.¶
X-FADP-Proof header of a
subsequent request, asserting that the agent has executed an on-chain
transfer matching the payment challenge.¶
A FADP interaction consists of three HTTP exchanges:¶
X-FADP-Required header describing the
payment terms. The agent executes an on-chain transfer matching
those terms.¶
X-FADP-Proof header that
references the completed on-chain transfer and the challenge nonce.
The server verifies the proof and, if valid, fulfills the request.¶
Agent Server Verifier
| | |
| GET /resource | |
|----------------------------->| |
| | |
| 402 Payment Required | |
| X-FADP-Required: { | |
| version, amount, token, | |
| chain, payTo, nonce, | |
| expires, verifyUrl } | |
|<-----------------------------| |
| | |
| [Agent executes on-chain transfer to payTo] |
| [Receives txHash from blockchain] |
| | |
| GET /resource | |
| X-FADP-Proof: { | |
| txHash, nonce, timestamp }| |
|----------------------------->| |
| | POST verifyUrl |
| | { txHash, payTo, |
| | amount, token, |
| | chain, nonce } |
| |------------------------->|
| | |
| | { verified: true, |
| | from, to, amount } |
| |<-------------------------|
| | |
| 200 OK + resource data | |
|<-----------------------------| |
The X-FADP-Required response header field is sent by the
server in a 402 response. Its value is a JSON object with the
following members:¶
"1.0" for this version of
the protocol.¶
"0.001"). The server SHOULD use the minimal
number of decimal places necessary to avoid ambiguity.¶
"USDC", "ETH",
"USDT"). The symbol SHOULD conform to the canonical
symbol registered with the issuer or a well-known token list.¶
"base" (Base Mainnet), "ethereum" (Ethereum
Mainnet), and "solana" (Solana Mainnet). Implementors
MAY define additional chain identifiers using reverse-DNS
notation to avoid collision.¶
"Premium market data API").
Intended for display in agent UIs and transaction logs.¶
https://fluidnative.com/v1/fadp/verify. Servers
operating their own verification infrastructure SHOULD set this
field.¶
Example value (formatted for readability; actual header value MUST be a single-line JSON string):¶
{
"version": "1.0",
"amount": "0.001",
"token": "USDC",
"chain": "base",
"payTo": "0xAbCd1234AbCd1234AbCd1234AbCd1234AbCd1234",
"nonce": "a3f9c2b1d4e5f6a7b8c9d0e1f2a3b4c5",
"expires": 1745001234,
"description": "GPT-4o inference via OpenRouter proxy",
"verifyUrl": "https://fluidnative.com/v1/fadp/verify"
}
¶
The X-FADP-Proof request header field is sent by the agent
in the authenticated request. Its value is a JSON object with the
following members:¶
X-FADP-Required header of the payment challenge to which
this proof responds. The server MUST verify that this nonce
matches a known, unexpired, unconsumed challenge.¶
|currentTime - timestamp| > 300 seconds.¶
fwag_
key), used for logging and audit. Implementations MUST NOT
include the full credential.¶
Example:¶
{
"txHash": "0xabc1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcd",
"nonce": "a3f9c2b1d4e5f6a7b8c9d0e1f2a3b4c5",
"timestamp": 1745001200,
"agentKeyPrefix": "fwag_a3f9"
}
¶
The verification endpoint is an HTTPS resource that the server (or its delegate) calls to confirm that a payment proof corresponds to a valid on-chain transfer. This section defines the request and response formats for that endpoint.¶
The server sends an HTTP POST to the verifyUrl with a
JSON body containing:¶
The verification service responds with a JSON object:¶
REQUIRED. Boolean. true if and only if all of the
following conditions hold:¶
payTo).¶
verified is false.¶
Example successful response:¶
{
"verified": true,
"txHash": "0xabc123...",
"amount": "0.001",
"token": "USDC",
"chain": "base",
"from": "0xAgentWallet...",
"to": "0xServerWallet..."
}
¶
Example failed response:¶
{
"verified": false,
"error": "Transfer amount 0.0005 USDC is less than required 0.001 USDC"
}
¶
When a server receives a request for a FADP-protected resource
without an X-FADP-Proof header, it MUST:¶
X-FADP-Required header to a JSON object as defined in Section 4.1.¶
Access-Control-Expose-Headers: X-FADP-Required to ensure cross-origin agents can read the header.¶
When a server receives a request with an X-FADP-Proof header,
it MUST perform the following checks in order, returning an appropriate
error response if any check fails:¶
txHash, nonce, and timestamp are present; return 400 if any is absent.¶
|currentTime - proof.timestamp| <= 300 seconds; return 402 if outside range.¶
verifyUrl; return 402 if verified is false.¶
Step 7 (nonce consumption) MUST occur before the server fulfills the request. If the server cannot atomically consume the nonce and fulfill the request (e.g., due to a crash), it SHOULD err on the side of not consuming the nonce, accepting the risk of a duplicate fulfillment rather than silently accepting payment without delivering service.¶
An agent implementation SHOULD:¶
X-FADP-Required, validate that the
requested amount does not exceed the agent's configured spending limit
before proceeding.¶
amount
of the specified token.¶
X-FADP-Proof object containing the
txHash, the nonce from the challenge, and the current
Unix timestamp.¶
X-FADP-Proof header added.¶
An agent MUST NOT reuse a txHash or nonce across
separate request/response cycles. Each resource access requires a
fresh payment and a fresh proof.¶
FADP servers SHOULD include a JSON body in all error responses with at least the following fields:¶
"FADP/1.0" to identify the protocol version.¶
| HTTP Status | Condition | Recommended error value |
|---|---|---|
| 400 | Malformed X-FADP-Proof header (not valid JSON) |
invalid_proof_format
|
| 400 | Missing required fields in proof |
missing_proof_fields
|
| 402 | No proof header present (initial challenge) |
payment_required
|
| 402 | Nonce unknown (never issued or already expired from store) |
unknown_nonce
|
| 402 | Nonce expired (TTL elapsed) |
nonce_expired
|
| 402 | Proof timestamp too old or too far in future |
proof_timestamp_invalid
|
| 402 | On-chain verification returned verified: false
|
payment_verification_failed
|
| 402 | Transferred amount less than required |
insufficient_payment
|
| 403 | Nonce has already been consumed (replay attempt) |
nonce_already_used
|
FADP uses short string identifiers for blockchain networks. The following values are defined by this specification:¶
| Identifier | Network | Native Currency | EVM Chain ID |
|---|---|---|---|
base
|
Base Mainnet (Coinbase L2) | ETH | 8453 |
ethereum
|
Ethereum Mainnet | ETH | 1 |
solana
|
Solana Mainnet Beta | SOL | N/A |
injective
|
Injective Mainnet | INJ | N/A |
base-sepolia
|
Base Sepolia Testnet | ETH | 84532 |
Implementors that wish to support chains not listed here SHOULD use
identifiers of the form {namespace}-{networkname} to avoid
collisions with future registered values.¶
The nonce mechanism is the primary defense against replay attacks.
A valid txHash from a past payment cannot be reused
because:¶
Server implementations MUST use cryptographically secure random number
generation for nonces (e.g., /dev/urandom or equivalent).
Predictable nonces would allow an attacker to pre-compute valid proofs.¶
The nonce store MUST be shared across all instances of a horizontally scaled server deployment. If a local per-process nonce store is used, the same nonce could be accepted by two different instances simultaneously, creating a replay window. A distributed cache (e.g., Redis) or a database with atomic compare-and-delete operations is RECOMMENDED for production deployments.¶
The verification service checks that the transferred amount is at least the required amount. Servers SHOULD NOT issue refunds for overpayments, as the complexity of doing so on-chain outweighs the benefit for small amounts. Agents SHOULD transfer exactly the required amount to avoid unnecessary token loss.¶
In principle, an attacker observing the agent's on-chain transaction
in the mempool could copy the txHash and attempt to submit
a proof before the legitimate agent. This attack is mitigated by:¶
Servers that require strong session binding MAY add an additional check verifying that the HTTP session initiating the proof matches the session that triggered the original challenge (e.g., via a session cookie or TLS channel binding), though this is outside the scope of the current protocol version.¶
Servers that delegate verification to a third-party service are
implicitly trusting that service's honesty and availability. A
compromised or malicious verification service could return
verified: true for invalid proofs, allowing unauthorized
access.¶
Servers operating in high-value contexts SHOULD run their own verification infrastructure against a direct blockchain RPC endpoint. The verification endpoint API defined in Section 5 is designed to be self-hostable for this reason.¶
On chains with probabilistic finality (including Ethereum and Base), a transaction that appears in a block may be reorged out of the canonical chain. Servers accepting payments for high-value resources SHOULD wait for a chain-specific number of confirmation blocks before accepting a proof as final. For low-value micropayments on Base (an optimistic rollup with fast soft-finality), a single block confirmation is typically sufficient.¶
Verification services MUST check that the transaction receipt status indicates success (i.e., it was not reverted), not merely that a transaction with the given hash exists.¶
An adversary could generate large numbers of initial requests to force the server to allocate nonces, potentially exhausting memory if the nonce store grows without bound. Server implementations MUST periodically prune expired nonces and SHOULD rate-limit the issuance of payment challenges per IP address or session.¶
The X-FADP-Required and X-FADP-Proof header values
are JSON strings. Implementations MUST parse these with a
conformant JSON parser and MUST NOT construct them via string
interpolation without proper escaping, to prevent injection attacks.¶
All FADP exchanges, including calls to the verification service, MUST be made over TLS (HTTPS). Transmitting payment challenges or proofs over plaintext HTTP exposes the nonce to network adversaries, potentially enabling race-condition replay attacks.¶
FADP does not define agent-side spending controls; these are the
responsibility of the agent runtime. However, agent implementors
MUST validate the requested amount in the payment challenge
against a pre-configured limit before executing any transfer.
Failing to do so could allow a malicious server to drain an agent's
wallet by issuing artificially large payment challenges.¶
This document requests registration of the following header fields in the "Hypertext Transfer Protocol (HTTP) Field Name Registry" maintained at https://www.iana.org/assignments/http-fields/.¶
X-FADP-Required¶
X-FADP-Proof¶
No new media types are registered by this document. All message
bodies are application/json as defined in
[RFC8259].¶
Reference implementations of the server middleware
(fadpGate()) and client interceptor
(fadpFetch()) are available as open-source software:¶
agent.fetch() method.
Repository: https://github.com/fluidbase9/fluidwalletbase¶
For single-process servers, an in-memory Map with periodic
TTL pruning is sufficient. For multi-instance deployments, a shared
store with atomic operations is required. A Redis
SET NX EX command provides an atomic "set if not exists with
expiry" primitive suitable for nonce issuance; a Redis DEL
returning the count of deleted keys provides atomic consumption.¶
Token amounts MUST be represented as decimal strings to avoid
floating-point precision loss. On-chain, USDC uses 6 decimal places;
the string "0.001" corresponds to on-chain value
1000 (in the smallest unit). Implementations MUST convert
between decimal string and on-chain integer representation using
fixed-point arithmetic, not IEEE 754 floating-point.¶
Browser-based agent implementations require that
X-FADP-Required be listed in the
Access-Control-Expose-Headers response header for the
402 response. Servers MUST set this header when cross-origin
clients are expected.¶
The following illustrates a complete FADP exchange over HTTP/1.1.¶
Step 1 — Initial Request (no proof):¶
POST /v1/chat/completions HTTP/1.1
Host: proxy.example.com
Content-Type: application/json
{"model":"openai/gpt-4o","messages":[{"role":"user","content":"Hello"}]}
¶
Step 2 — Payment Challenge:¶
HTTP/1.1 402 Payment Required
Content-Type: application/json
X-FADP-Required: {"version":"1.0","amount":"0.001","token":"USDC",
"chain":"base","payTo":"0xAbCd1234AbCd1234AbCd1234AbCd1234AbCd1234",
"nonce":"a3f9c2b1d4e5f6a7b8c9d0e1f2a3b4c5","expires":1745001534,
"description":"GPT-4o inference","verifyUrl":"https://fluidnative.com/v1/fadp/verify"}
Access-Control-Expose-Headers: X-FADP-Required
{"error":"Payment required","protocol":"FADP/1.0"}
¶
Step 3 — Agent executes on-chain USDC transfer on Base, receives txHash.¶
Step 4 — Authenticated Request:¶
POST /v1/chat/completions HTTP/1.1
Host: proxy.example.com
Content-Type: application/json
X-FADP-Proof: {"txHash":"0xabc123...","nonce":"a3f9c2b1d4e5f6a7b8c9d0e1f2a3b4c5",
"timestamp":1745001480}
{"model":"openai/gpt-4o","messages":[{"role":"user","content":"Hello"}]}
¶
Step 5 — Successful Response (after on-chain verification):¶
HTTP/1.1 200 OK
Content-Type: application/json
{"choices":[{"message":{"role":"assistant","content":"Hello! How can I help?"}}]}
¶
The author thanks the teams building open agent infrastructure across the Ethereum, Base, and Solana ecosystems whose work made practical micropayment settlement possible. The design of FADP was informed by the x402 protocol from Coinbase Developer Platform, the Model Context Protocol (MCP), and early feedback from developers building autonomous agents on the Fluid Wallet platform.¶