This document is the dense reference companion to the public guide Settlement with existing payment providers. It describes how Paybond sits alongside Stripe and Coinbase without replacing them, and maps the HTTP surfaces operators and integrators touch in production.
Design principles
- Destinations are server-owned. Tenant settlement configuration in Postgres (
paybond_tenant_settlement_config) is the source of truth for Connect account ids, Base USDC receive addresses, MPP profile ids, and Tempo session settings. Harbor snapshots resolved values onto each intent at create time (settlement.rs,settlementconfig/config.go). - Funding gates are provider-scoped. Stripe
payment_intent.succeeded, Coinbase authorization events, and MPP Payment Auth verification are Harbor-internal signals. They are not substitutes for payee completion evidence. - Terminal settlement is evidence-driven.
drive_terminal_settlementruns only fromevidence_submitted, after predicate evaluation. Release vs refund is derived from the stored evaluation — not chosen by the confirm caller. - Tenant isolation at every hop. Gateway webhook preflight rejects events without binding metadata or with Connect destination mismatches. Internal automation routes require tenant-scoped bearer secrets or mTLS client certs with
urn:paybond:tenant:<realm>URI SAN.
Three-layer architecture
sequenceDiagram
autonumber
actor Admin as Tenant admin
participant GW as Gateway
participant PG as Postgres control plane
participant HB as Harbor
participant PSP as Stripe / Coinbase / Tempo
actor App as Kit / application
Admin->>GW: Save settlement config (console or PUT /v1/admin/settlement/config)
GW->>PG: Immutable settlement config version
App->>GW: POST /harbor/intents (tenant API key)
GW->>HB: Forward create (mTLS)
HB->>PG: Read allowed rails + destination snapshot
HB->>PSP: Initialize funding (rail-specific)
PSP-->>HB: Authorized / pending / challenge
PSP->>GW: Webhook (Stripe / Coinbase Hook0)
GW->>GW: Verify signature, enqueue paybond_webhook_job
GW->>HB: POST /internal/v1/stripe/events or /internal/v1/coinbase/events
HB-->>HB: Fund gate, provider state hydrate
App->>GW: POST evidence + settlement/confirm
HB->>PSP: Capture / void / transfer / refund (terminal)
HB-->>GW: released or refundedLayer responsibilities
| Layer | Owns | Does not own |
|---|---|---|
| Gateway | Auth, settlement config CRUD, webhook ingress, job queue, dispute cases, Stripe webhook-health UI data | Predicate evaluation, ledger append, PaymentIntent creation |
| Harbor | Intent state machine, funding handshake, evidence + predicate VM, drive_terminal_settlement, ledger events | Long-lived Postgres dispute case rows |
| Postgres (Gateway) | paybond_tenant_settlement_config, webhook job queue, paybond_stripe_webhook_event | Intent escrow rows (Harbor sled) |
Per-rail reference
| Rail | Provider touchpoint | Funds commit | Terminal release | Terminal refund | Async / webhook path |
|---|---|---|---|---|---|
stripe_connect | PaymentIntent on linked Connect destination | Create-time authorization (typical) | PI capture | PI cancel | Optional PI reconcile via recovery |
stripe_ach_debit | ACH PaymentIntent | payment_intent.succeeded | Transfer / capture path on stored PI | Refund on stored charge | Stripe webhook → Gateway → Harbor /internal/v1/stripe/events |
x402_usdc_base | Coinbase payment session (Base) | /fund + authorization success | Coinbase capture | Coinbase void | Hook0 → Gateway → Harbor /internal/v1/coinbase/events |
stripe_mpp | Payment Auth charge (Stripe) or Tempo session | /fund credential verified | Charge: PI capture; Session: evidence-driven release after vouchers | Charge: cancel/refund driver; Session: rail-specific refund | Charge: payment_intent.succeeded ingest; Session: Tempo RPC recovery |
stripe_connect
- Harbor initializes a PaymentIntent against the intent-snapshotted Connect destination during create when the live Stripe runtime is enabled.
capability_tokenis often available in the create response.drive_terminal_settlementwithpassed: truecaptures the held PI;passed: falsecancels it.
stripe_ach_debit
- Shares Connect destination with card rail; requires ACH debit capability ready in settlement config.
- Intent may remain pre-
fundeduntil Stripe confirms the bank debit. - Webhook events of interest include
payment_intent.succeeded,charge.failed,mandate.updated, and dispute/refund families — see Operations runbook §2. - Reconciliation (
POST /internal/v1/stripe/reconcile) refreshes stored provider fields only; it does not mutate money.
x402_usdc_base
- Amounts are USD-denominated (cents); settlement executes in USDC on Base per session authorization.
- Gateway Coinbase webhooks use Hook0 signature verification with production timestamp tolerance 90s (configurable via
PAYBOND_WEBHOOK_TIMESTAMP_TOLERANCE_SECS). - Harbor deduplicates via durable webhook epoch +
eventId+ body hash (coinbase_webhook_begin_processing). - After sled restore, operators must rotate Hook0 secrets and bump per-tenant webhook epoch — see runbook §2 x402 section.
stripe_mpp (Beta Preview)
- Funding never completes on create alone; all paths go through
POST /intents/{id}/fundPayment Auth. - Charge (
intent="charge"): Stripe PI;payment_intent.succeededwebhook can complete funding if the client drops mid-handshake. - Session (
intent="session"): Tempo deposit confirmation;session_open_pendinguntil on-chain confirm; vouchers atPOST /verifymeter spend under intent budget. - Operational checklist: MPP hardening.
Post-funding terminal settlement
Harbor handler flow:
- Payee submits evidence →
POST /intents/{id}/evidence→ predicate VM evaluation →evidence_submitted. - Caller confirms →
POST /intents/{id}/settlement/confirm→drive_terminal_settlement(runtime, intent, tenant, sandbox, passed, ...). - Rail driver executes capture/void/transfer/refund; intent transitions to
releasedorrefunded; ledger appends terminal events.
drive_terminal_settlement returns ConflictState if the intent is not in evidence_submitted. Idempotent if already terminal.
Dispute freeze (disputed) blocks terminal settlement until Harbor dispute/resolve — see Intent lifecycle and Disputes and evidence.
HTTP surface (Gateway and Harbor)
Tenant-authenticated (public API)
| Method | Path | Role |
|---|---|---|
GET | /v1/admin/settlement/config | Read settlement config (masked for read-only principals) |
PUT | /v1/admin/settlement/config | Update rails, destinations, MPP profile, x402 address |
POST | /harbor/intents | Create signed intent (Gateway proxy to Harbor) |
POST | /harbor/intents/{id}/fund | Funding handshake (x402, MPP, ACH retry) |
POST | /harbor/intents/{id}/evidence | Submit payee evidence |
POST | /harbor/intents/{id}/settlement/confirm | Terminal settlement from evaluation |
GET | /v1/stripe/webhook-health | Stripe webhook delivery health (console Settlements) |
Full schemas: Gateway OpenAPI, Harbor OpenAPI.
Provider webhook ingress (unsigned provider → Gateway)
| Method | Path | Notes |
|---|---|---|
POST | /webhooks/stripe | Legacy combined endpoint |
POST | /webhooks/live/stripe | Live environment Stripe events |
POST | /webhooks/sandbox/stripe | Sandbox environment Stripe events |
POST | /webhooks/coinbase | Coinbase Hook0 (x402) |
POST | /webhooks/live/coinbase | Live Coinbase |
POST | /webhooks/sandbox/coinbase | Sandbox Coinbase |
Verified events enqueue in paybond_webhook_job (idempotency key = provider event id) before HTTP 2xx to the provider.
Internal automation (mTLS and/or tenant-bound bearer)
| Method | Path | Auth | Purpose |
|---|---|---|---|
POST | /internal/v1/stripe/events | Harbor forward bearer + Stripe signature re-verify | Stripe funding/settlement ingest |
POST | /internal/v1/stripe/reconcile | PAYBOND_STRIPE_RECONCILIATION_SECRETS per tenant | Read-only Stripe status refresh |
GET | /internal/v1/stripe/webhook-failures | Internal automation bearer | Break-glass webhook triage |
POST | /internal/v1/coinbase/events | Harbor forward bearer + Hook0 metadata | Coinbase x402 ingest |
POST | /internal/v1/coinbase/webhook-epoch/restore | PAYBOND_HARBOR_INTERNAL_AUTOMATION_SECRET | Post-restore replay guard |
Gateway forwards webhooks using PAYBOND_HARBOR_INTERNAL_WEBHOOK_FORWARD_SECRET (with optional _PREVIOUS overlap). See Secrets and key rotation.
Stuck-intent recovery
| Scenario | Detection | Safe response |
|---|---|---|
| ACH pending | Intent pre-funded, Stripe PI processing | Wait for webhook or run tenant-scoped Stripe reconcile; do not fake funded |
| x402 session incomplete | /fund 402 loop, missing authorization | Retry canonical /fund; verify Coinbase webhook reached Gateway |
MPP session_open_pending | Harbor funding status, 202 responses | Tempo RPC recovery (PAYBOND_HARBOR_RECOVERY_MPP_TEMPO_RECONCILE); check PAYBOND_TEMPO_RPC_URL |
| Webhook missed | webhook-health failures, Harbor drift | Stripe reconcile or Harbor recovery tick; preserve stored provider ids |
| Terminal settlement retry cap | settlement_last_error on intent | Operator runbook §2; escalate if PI vs Harbor lifecycle mismatch persists |
Harbor background recovery (when env flags enabled):
PAYBOND_HARBOR_RECOVERY_STRIPE_RECONCILE— retrieve Stripe status for non-terminal intents with stored PI ids.- Coinbase session polling for non-terminal x402 intents with
payment_session_id. - MPP charge recovery via Stripe PI retrieve; session via Tempo deposit poll.
Recovery updates local status and safe provider fields only — no capture, transfer, or refund from reconcile alone.
Sandbox vs production
| Mode | Settlement runtime | Webhooks |
|---|---|---|
| Sandbox tenant | Simulator rails; optional Stripe test-mode MPP | Environment-scoped webhook URLs; simulator events |
| Production | Live Stripe, Coinbase CDP, Tempo RPC for MPP session | Live webhook secrets; 90s Hook0 tolerance in hosted config |
PAYBOND_SETTLEMENT_MODE=simulated is for local engineering only. Hosted sandbox uses Stripe test-mode and simulator routing per tenant environment.
Related
- Settlement with existing payment providers — adopter-facing guide
- Configure settlement rails — console setup
- Intent lifecycle — state machine
- Settlement flows — design sequences
- Operations runbook §2 — incident triage
- MPP hardening — MPP production checklist