Quitanza

x402 adapter

The @quitanza/x402 adapter maps the HTTP 402 payment-required handshake onto the Quitanza escrow lifecycle, so an x402-style paid request settles with recourse and ends in a quitanza instead of a bare transfer. The adapter is live today on simulated rails (scheme quitanza-sandbox, network quitanza-local); integration with external x402 facilitators is in development.

The handshake, settled through escrow

  1. The client requests a paid resource. The server answers 402 Payment Required with an accepts array of payment requirements: price, asset, resource id, and the server's Ed25519 key as payTo.
  2. The client builds a payment authorization, a signature over canonical {amount, asset, from, payTo, resource}, and retries with it base64-encoded in the X-PAYMENT header.
  3. The server verifies the authorization, runs a full escrow lifecycle for the request (create → fund → deliver the resource → verify → settle), and responds with the resource plus an X-PAYMENT-RESPONSE header naming the escrow and the quitanza that proves the matter closed.

Every step lands on the escrow's hash-chained evidence trail, exactly as in a long-form escrow.

Try it against the sandbox

The local API serves a live demo resource:

GET /v1/x402/demo
→ 402 { "x402Version": 1, "accepts": [ { "scheme": "quitanza-sandbox", "maxAmountRequired": "0.10", … } ], "error": "…" }

Client side, with the adapter:

import { createPaymentHeader } from "@quitanza/x402";
import { generateKeypair } from "@quitanza/core";

const payer = generateKeypair();
const offer = (await (await fetch(url)).json()).accepts[0];
const paid = await fetch(url, {
  headers: { "X-PAYMENT": createPaymentHeader(offer, payer) }
});
// paid.headers.get("X-PAYMENT-RESPONSE") names the quitanza.

Server side, X402Gateway wraps any resource:

import { X402Gateway } from "@quitanza/x402";

const gateway = new X402Gateway({ engine, payTo: serverKeys });
const requirements = gateway.requirements({
  resource: "/reports/q2",
  amount: "0.10",
  asset: "USDC",
  description: "Q2 report"
});
// no X-PAYMENT header → respond 402 with gateway.paymentRequired(requirements)
// valid header → gateway.settle(header, requirements, resource) returns
// { escrow, delivery, verdict, quitanza, responseHeader }

Why escrow under 402

A bare 402 payment is fire-and-forget: the client pays, and what arrives is whatever arrives. Routed through Quitanza, the same handshake gains verification against terms, a dispute path, timeout guarantees, and a terminal proof either party can hold.

Status

Piece State
402 handshake, X-PAYMENT / X-PAYMENT-RESPONSE headers Live
Escrow lifecycle per paid request, quitanza issued Live
Rails Simulated (quitanza-local): no chain, no real funds
External facilitator integration In development

This page as markdown