paybondpaybond
Sign in

Intent lifecycle

How a Paybond intent moves from creation and funding through evidence, settlement, refund, or dispute.

A Paybond intent is the signed record of a commercial commitment between a principal and a payee. It defines the amount at stake, the evidence the payee can submit, and the rule used to decide whether funds are released or refunded.

As the intent progresses, Paybond records each state change in Harbor (agent transaction engine) and reflects terminal outcomes in Signal.

State diagram

stateDiagram-v2
  [*] --> created
  created --> funded: funding authorized
  funded --> evidence_submitted: evidence submitted
  evidence_submitted --> released: evidence accepted, release confirmed
  evidence_submitted --> refunded: evidence rejected, refund confirmed
  funded --> disputed: dispute opened
  evidence_submitted --> disputed: dispute opened
  disputed --> released: dispute resolved to release
  disputed --> refunded: dispute resolved to refund
  released --> [*]
  refunded --> [*]

Transitions

1. Create (POST /intents)

  • The principal creates a signed intent describing the amount, currency, deadline, parties, evidence requirements, and release rule for the transaction.
  • Paybond validates the intent before accepting it, including the evidence rule that will be used later during evaluation.
  • Retrying the same create request with the same idempotency key returns the original result instead of creating a duplicate intent.

2. Fund (funded)

  • The intent moves to funded when the underlying funding source is authorized.
  • In Stripe Connect deployments, that means the rail has authorized the funding during intent creation where the tenant and runtime are configured for Stripe.
  • For stripe_ach_debit, ACH debit is delayed-confirmation funding. Harbor records the funding attempt while the bank debit is pending and moves the intent to funded only after Paybond receives final rail confirmation.
  • For x402_usdc_base, the POST /intents/{id}/fund route advances the payment-session handshake and moves the intent to funded after authorization succeeds.
  • For stripe_mpp (Stripe Machine Payments Protocol), the same /fund route runs a Payment Auth handshake:
    1. First /fund without a credential returns 402 with WWW-Authenticate: Payment … challenge(s) and funding.status = payment_required.
    2. The client retries with an app-owned credential on x-paybond-payment-authorization (via Gateway) or Authorization: Payment (direct Harbor).
    3. Harbor verifies the credential, confirms charge payment (funding.status = charge_succeeded) or Tempo session deposit (deposit_confirmed), returns 200 with Payment-Receipt, and mints the capability_token. Live session funding may return 202 with session_open_pending while the open transaction confirms on-chain; Kit helpers and Harbor recovery poll until funded. Create and fund responses expose extended funding fields: Payment Auth intent/method/challenge_id, settlement denomination (settlement_asset, settlement_network, deposit_amount_base_units), and Tempo session channel state when applicable. In sandbox, the first charge challenge may include a parallel session challenge when Tempo session funding is enabled for the tenant (mpp_session_enabled = true and mpp_tempo_recipient_address configured). Kit helpers fundWithMppCharge / fundWithMppSession (TypeScript) and fund_with_mpp_charge / fund_with_mpp_session (Python) orchestrate credential creation and retries — see Harbor MPP handshake, Fund Stripe MPP intents, and the support matrix.
  • For stripe_mpp session intents after funding, each guarded tool call may require a Tempo voucher on POST /verify in addition to the capability token. Harbor rejects vouchers whose cumulative total exceeds the signed intent budget (amount_cents), allows only one pending voucher per intent, and leaves provider state unchanged on rejection. See Session voucher metering at verify.
  • In simulated or disabled runtimes, responses reflect the configured non-production behavior instead of promising live money movement.

3. Submit evidence (POST /intents/{id}/evidence)

  • The payee submits signed evidence for the intent. Paybond evaluates that evidence against the rule attached to the intent and returns an evaluation report.
  • A passing evaluation makes the intent eligible for release. A failing evaluation is recorded as part of the lifecycle rather than treated as a malformed request, and the intent can then proceed to refund or dispute review.

4. Confirm settlement (POST /intents/{id}/settlement/confirm)

  • Settlement confirmation turns the recorded predicate result into a money outcome.
  • If the predicate passed, Harbor releases funds to the payee and moves the intent to released.
  • If the predicate failed, Harbor refunds or cancels through the active rail and moves the intent to refunded.
  • The caller does not choose the release/refund outcome on this route; Harbor derives it from the evidence evaluation already attached to the intent.
  • For managed completion_budget_v1 policies, a passing evaluation also freezes the reported cost_cents from validated signed evidence as the trusted settlement amount. Supported rails capture or transfer only that amount and leave/release the unused authorization; unsupported provider contracts reject before any money operation. See Variable-cost settlement by rail.
  • If Paybond and the payment rail fall out of sync, operators can use recovery workflows described in Operational surfaces.

5. Dispute

  • A dispute can be opened after funding or after evidence submission. This freezes settlement and moves the intent to disputed.
  • Paybond keeps a tenant-scoped dispute case with timeline, evidence references, internal notes, and an exportable arbitration handoff packet. See /v1/disputes/cases/* in the Gateway API.
  • Harbor resolves money movement from disputed to released or refunded. Gateway dispute cases can also record non-rail case statuses such as resolved_split or escalated_external; those are case workflow statuses, not Harbor intent states.

Terminal outcomes and case statuses

State or statusMeaning
releasedHarbor terminal money state. Funds have been released to the payee.
refundedHarbor terminal money state. Funds have been returned to the principal.
disputedHarbor review/freeze state. Signal v1 records the dispute event as a disputed outcome when it is the first ingested terminal outcome for the intent.
resolved_splitGateway dispute-case status for a split or other off-rail resolution; not a Harbor intent state.
escalated_externalGateway dispute-case status for external review or arbitration handoff; not a Harbor intent state.

Signal recomputes scores when it ingests signed Harbor outcome events (released, refunded, or disputed). Outcome rows are idempotent per intent, so later review workflow updates do not silently rewrite the signed score. Lifecycle latency is measured from intent creation to the ingested outcome event.

Signing versions

signing_versionPayloadNotes
6 (IntentCreationSignV6)Raw predicate_dsl plus bound payee_pubkey and settlement_rail.Required for fundable intents with inline predicates.
7 (IntentCreationSignV7)Managed policy_binding plus bound payee_pubkey and settlement_rail.Required for fundable intents that reference a published policy head.
4 (IntentCreationSignV4)Legacy raw-predicate envelope without payee binding.Deprecated — rejected for fundable intents and in live environments.
5 (IntentCreationSignV5)Legacy policy-binding envelope without payee binding.Deprecated — rejected for fundable intents and in live environments.

SDKs and hosted integrations emit signing v6/v7 automatically. If you are implementing an offline signer, follow the Harbor API and SDK signing rules so the payload matches Paybond's canonical format and includes payee_pubkey.

Recovery and idempotency

  • Paybond includes recovery workflows for intents that become stuck after a crash, timeout, or payment-provider outage.
  • Operators can list intents that need recovery attention and reconcile them before retrying settlement.
  • All mutating POST endpoints honor tenant-scoped, operation-scoped idempotency-key values so retries do not create duplicate lifecycle actions.