SKU#21 · ruleset x402-auth-capture-hold-v1

Auth-capture hold LIVE

Reserva fondos (escrow authorize), no inventario. El wire scheme es auth-capture, no exact. HTTP 200 es HOLD, no settle. La verdad de settle es el status Coinbase Checkout COMPLETED.

Diff vs SKU#16 brief

  • /api/reserve/brief — informativo, wire exact $0.01, no hold on-chain.
  • /api/reserve/hold — LIVE, wire auth-capture $0.05 (amount 50000), escrow on-chain, ruleset x402-auth-capture-hold-v1 solamente.

Endpoints

GET /api/reserve/hold — sin query ni body requeridos. x402 v2 auth-capture, $0.05 USDC en Base (eip155:8453, amount atómico 50000). Sin pago responde HTTP 402 + PAYMENT-REQUIRED. En live, el server crea un Coinbase Business Checkout y bindea checkoutId / x402_url.

Poll: GET /api/reserve/hold?checkoutId=<id> — status ACTIVE|PROCESSING|COMPLETED|FAILED|EXPIRED. Si COMPLETED, incluye transactionHash.

Refund (post-COMPLETED): POST /api/reserve/hold/{holdId}/refund (holdId === checkoutId; body opcional { amount?, reason? }).

Void: Checkouts permite deactivate solo de ACTIVE (impago). Después del authorize, void es N/A — Coinbase captura server-side; esperar EXPIRED o refund post-COMPLETED. Pre-authorize: POST /api/reserve/hold/{holdId}/void.

Probe unpaid (debe ser 402 tras el deploy, scheme auth-capture):

curl -i 'https://lupariel.com/api/reserve/hold'

Clients exact-only (incluido CdpX402Client sin AuthCaptureEvmScheme) fallan. Facilitators públicos (PayAI) no settlean auth-capture: el backend es Coinbase Business Checkouts.

Respuesta 200 HOLD (post-authorize)

{
  "product": "LupaRiel",
  "kind": "reserve-hold",
  "scheme": "auth-capture",
  "status": "authorized",
  "holdId": "<checkoutId>",
  "checkoutId": "<checkoutId>",
  "amount": "0.05",
  "asset": "USDC",
  "network": "eip155:8453",
  "payTo": "0x6fc99c8a5334e00f6fce854700959930a3c62dbc",
  "autoCapture": true,
  "settlementTruth": "COMPLETED (checkout status), not HTTP 200 authorize",
  "notInventory": true,
  "txAuthorize": null,
  "poll": "GET /api/reserve/hold?checkoutId=<id>",
  "void": "N/A after authorize; wait EXPIRED or refund post-COMPLETED. ACTIVE-only deactivate: POST /api/reserve/hold/<id>/void",
  "capture": "Coinbase Checkouts captures server-side after authorize. No merchant captureAuthorizer in this path.",
  "refund": "POST /api/reserve/hold/<id>/refund",
  "ruleset": "x402-auth-capture-hold-v1",
  "disclaimer": "Reserva fondos (escrow), no inventario."
}

Secrets de Pages (nombres, no valores)

  • PAY_TO — mismo wallet de la serie
  • CDP_API_KEY_ID — Coinbase Business Checkouts
  • CDP_API_KEY_SECRET — JWT Ed25519 / ES256 para create / get / refund / deactivate

Directo merge + wrangler pages deploy WITH Functions. No hardcodear wallets buyer.

Discovery: /openapi.json y /.well-known/x402.