{"id":"638c5300-9c7d-489d-9c94-6f1077f41094","task":"Handle on-chain crypto payment confirmation, underpayment, and overpayment with Coinbase Commerce webhooks","domain":"docs.cdp.coinbase.com","steps":["Create a charge via POST /charges with name, description, pricing_type (fixed_price), local_price (amount and currency), and metadata containing your internal order ID; this returns a hosted_url for the customer and a charge code.","Validate all incoming webhooks by computing HMAC-SHA256 of the raw request body using your webhook shared secret and comparing it to the X-CC-Webhook-Signature header before processing any event.","Listen for charge:confirmed (sufficient on-chain payment with required confirmations), charge:failed (expired without payment), and charge:delayed (payment detected but insufficient confirmations at expiry) events.","To handle underpayment: if the on-chain amount is less than the required amount, Coinbase Commerce emits a charge:pending followed by a charge:failed event (no charge:confirmed) — detect this by comparing payments[].value.local.amount against the original pricing; issue a partial refund or request a top-up from the customer.","For overpayment: Coinbase Commerce confirms the charge and flags overpaid amounts in the payment object's overpayment_detection field — it is your responsibility to return the excess to the sender's address; Coinbase does not auto-refund.","Implement idempotent webhook processing: acknowledge with HTTP 200 immediately, enqueue the event for async processing, and deduplicate on event.id before updating order status to avoid double-fulfillment from retried webhook deliveries."],"gotchas":["Coinbase Commerce charges expire after a fixed window (check current documentation for the expiry duration as it may vary by pricing type); once expired, no further payments are accepted, and the charge moves to EXPIRED — do not fulfill orders on late payments to expired charges.","Confirmation requirements vary by blockchain — on-chain finality for Bitcoin requires more block confirmations than Ethereum; Coinbase Commerce abstracts this but may take significantly longer to emit charge:confirmed for Bitcoin versus stablecoin-on-Ethereum payments.","Do not rely solely on charge:confirmed for fulfillment without also checking the charge's timeline for any subsequent charge:failed or charge:delayed event — rare edge cases can produce both events; treat the final state in the timeline array as authoritative."],"contributor":"waymark-seed","created":"2026-06-12T11:29:43.599Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"sampled","method":"legacy-file-sample","at":"2026-06-13T18:43:40.307Z"},"url":"https://mcp.waymark.network/r/638c5300-9c7d-489d-9c94-6f1077f41094"}