Why
The facilitator removes blockchain plumbing from the seller; it does not remove distributed-systems semantics. A paid API needs an idempotency key and a durable payment-to-resource state machine.
x402 makes stablecoin payment look like ordinary HTTP middleware: the server returns payment requirements, the client signs, and a facilitator verifies and settles. The difficult boundary appears when one stage succeeds and the next response is lost.
How it works
Put one idempotent API behind @x402/express, inject failures between verify, settle, and fulfillment, then prove that one signed payment produces at most one charge and one response entitlement.
PoC
Protect one idempotent API route with @x402/express. Inject a timeout after verification, after on-chain submission, after settlement, and after resource generation. Retry the identical signed request and assert two invariants: at most one payment settles, and one settled payment always maps to one durable entitlement.
What it proves
A facilitator removes node operation and settlement submission from the seller, but it cannot make a distributed workflow atomic. The application still needs a payment identifier, durable state, replay handling, and reconciliation between facilitator results and canonical receipts.
References: x402 facilitator, x402 v2 SDK.
Review clarification
The demo ends where the product begins
Returning HTTP 402 with payment requirements is an hour of work; the middleware makes the demo almost free. What the middleware cannot give you is the thing that makes it a product: the moment money moves in one system (the chain) and the good is delivered in another (your API), you have a distributed transaction, and distributed transactions cannot be made atomic. The real work sits exactly where the demo ends — the retry.
The failure window is between the stages
One "paid request" is four stages — verify → submit → settle → fulfill — each crossing a network boundary that can eat the response. That is why the PoC injects a timeout after each stage rather than failing the stages: every stage succeeded, only the response was lost, and the client does the only rational thing and retries the identical signed request.
| Window | What is true | What the retry must do |
|---|---|---|
| After verify | Nothing settled, no money moved | Re-verify and continue — the cheapest window |
| After submit | The dangerous one: did the transfer land? | The authorization nonce makes the chain refuse a second settle — so read "already used" as this payment already succeeded, never as an error to show the user |
| After settle | Money moved, no product yet | The debt exists only in your database — it must have been recorded durably before the crash |
| After fulfill | Resource exists, delivery lost | Return the same resource, never generate again |
Misclassifying the second window is how a paying customer gets an error screen for a payment that worked.
The two invariants are the whole product
At most one settled payment per signed request; exactly one durable entitlement per settled payment. Everything else — middleware, facilitator, SDK — is replaceable plumbing. This is exactly the Web2 payments playbook: Stripe's Idempotency-Key and a durable state machine (received → verified → submitted → settled → fulfilled) keyed by the payment nonce. x402 changes the rail, not the semantics. "Settlement owns the retry" means retry handling cannot live in generic HTTP retry logic; a retry is a lookup about an existing payment first, and a new attempt only after that lookup says so.
Vigilance is not the deliverable
You cannot monitor your way out of a double charge — by the time you see it, the money moved twice. The guarantee has to be structural: assume every response can be lost, treat the retry as the normal path, and ask in design review, for each arrow in the flow, "what happens if the response after this arrow is lost and the same request arrives again?" If any arrow answers "we charge again" or "we deliver nothing," that arrow is the bug — before any code is written. The reconciliation line at the end is receipt-is-not-settlement again: the facilitator saying "settled" is one service's claim; the canonical receipt on chain is the authority. And the reason x402 matters at all is agent commerce — pay-per-request with no account and no API key is the rail an AI agent would use.
Where it lands in Jayverse
- Verex: give every payment/order an idempotency key and a durable state machine. Track received → verified → submitted → settled → fulfilled per order so a retried checkout call after a lost response can't double-charge or double-fulfill.
- Wallet: treat "already used" as success, not error. When the wallet resubmits a signed tx after a lost response and the chain refuses a second settle, surface that as "this already went through," not a failure screen.
- Auditor: write down that the onchain receipt outranks a facilitator's "settled" claim. For any payment rail Verex adds, the canonical receipt is the authority; a service saying settlement completed is only a claim to reconcile against it.
Key expressions
| Expression | 뜻 · 쓰이는 자리 |
|---|---|
| idempotent | 멱등의, 같은 요청을 여러 번 보내도 결과가 같은 · API·결제 요청 설계에서 핵심 성질. "protect one idempotent API route" |
| idempotency key | 멱등성 키 · 같은 요청을 식별해 중복 처리를 막는 값. "Stripe's Idempotency-Key and a durable state machine" |
| plumbing | (비유) 배후 인프라, 배관 작업 · 겉으로 안 보이는 기반 시스템을 가리킬 때. "removes blockchain plumbing from the seller" |
| atomic | 원자적인, 쪼갤 수 없는 · 여러 단계가 한 번에 전부 성공하거나 실패해야 할 때. "distributed transactions cannot be made atomic" |
| reconciliation | 대사, 대조 확인 · 서로 다른 시스템의 기록이 일치하는지 맞춰보는 절차. "reconciliation between facilitator results and canonical receipts" |
| canonical | 기준이 되는, 정본의 · 여러 기록 중 진짜로 신뢰할 원본을 가리킬 때. "the canonical receipt on chain is the authority" |
| durable | 영속적인, 사라지지 않는 · 장애가 나도 남아 있어야 하는 상태·기록을 말할 때. "one durable entitlement per settled payment" |
| eat the response | 응답을 삼켜버리다, 유실시키다 · 네트워크 장애로 응답이 사라지는 상황. "a network boundary that can eat the response" |
| misclassify | 잘못 분류하다 · 상황을 틀리게 판단해 엉뚱하게 대응할 때. "gets an error screen for a payment that worked" |
| structural (guarantee) | 구조적인 (보장) · 사람의 주의력이 아니라 설계로 담보되는 안전장치. "the guarantee has to be structural" |
| x402 | HTTP 402(Payment Required) 상태 코드를 이용해 스테이블코인 결제를 HTTP 미들웨어로 만드는 프로토콜 · 에이전트가 계정·API 키 없이 요청마다 결제하게 하는 레일. "x402 turns payment into HTTP middleware" |
| facilitator | 결제 검증·정산을 대행하는 제3자 서비스(x402 프로토콜의 역할) · 블록체인 연동 작업을 판매자 대신 처리하지만 분산 트랜잭션 문제까지 없애주지는 않음. "The facilitator removes blockchain plumbing from the seller" |
| HTTP 402 | "결제 필요(Payment Required)" HTTP 상태 코드 · 원래 거의 쓰이지 않던 코드를 x402가 실제 결제 트리거로 되살려 쓰는 것. "Returning HTTP 402 with payment requirements is an hour of work" |