paybondpaybond
Sign in

Fund intents by rail

Production guide to creating Paybond intents and funding them on Stripe Connect, ACH debit, or x402 USDC — then using capability tokens with spend guard middleware.

In short: create the spend agreement, put money behind it, then get the one-time permission slip your tool call needs. This guide covers Steps 1–3 of How intent funding works: create a signed intent, fund it on the chosen rail, and use the returned capability_token with spend guard middleware.

Settlement rails must already be configured — see Configure settlement rails for tenant-admin console setup.

Open a tenant-bound session

Kit derives tenant scope from the service-account API key. Never pass tenant ids from unauthenticated user input.

paybond-session.ts

TS
TypeScript code sampleSwipe to inspect long lines
import { Paybond } from "@paybond/kit";

const paybond = await Paybond.open({
  apiKey: process.env.PAYBOND_API_KEY!,
  expectedEnvironment: "production",
});

Python: paybond = await Paybond.open(api_key=..., expected_environment="production").

Use sandbox credentials and expectedEnvironment: "sandbox" for rehearsal. For the fastest sandbox path without intent create, use one-command guardrails.

Step 1 — Create a signed intent

The principal signs budget, payee, deadline, allowed operations, evidence requirements, and settlement_rail. Pick a completion preset aligned with the rail when you want catalog-bound evidence.

paybond-session.ts

TS
TypeScript code sampleSwipe to inspect long lines
const created = await paybond.intents.create({
  operation: "travel.book_hotel",
  requestedSpendCents: 20_000,
  currency: "usd",
  settlementRail: "stripe_connect",
  completionPreset: "api_response_ok",
  // principal signing, payee, predicate, deadline — see quickstart
});

paybond_session.py

PY
Python code sampleSwipe to inspect long lines
created = await paybond.intents.create(
    operation="travel.book_hotel",
    requested_spend_cents=20_000,
    currency="usd",
    settlement_rail="stripe_connect",
    completion_preset="api_response_ok",
)

settlement_rail requests one allowed rail. Harbor resolves the payee destination from tenant settlement config — your create payload does not include Stripe account ids or wallet addresses.

Step 2 — Fund on the rail

RailTypical funding pathcapability_token timing
stripe_connectPaymentIntent authorized during create (or immediately after)Often in the create response
stripe_ach_debitBank debit initiated; Harbor waits for Stripe confirmationAfter payment_intent.succeeded — may require waiting or polling
x402_usdc_basepaybond.intents.fundWithX402 / fund_with_x402 on POST /harbor/intents/{id}/fundAfter authorization succeeds on Base
stripe_mpppaybond.intents.fundWithMppCharge / fundWithMppSession (or Python equivalents) on POST /harbor/intents/{id}/fundAfter charge payment or session deposit confirms (deposit_confirmed; session may pass through session_open_pending while Tempo confirms on-chain)
adyen_manual_captureCheckout authorization with manual capture during create (BYO merchant from settlement config)Often in the create response when Adyen returns Authorised; terminal capture/cancel still waits for webhooks
flutterwave_virtual_accountVA bank transfer into tenant-owned Virtual Account; Harbor waits for verified VA credit webhookAfter charge.completed / VA credit webhook confirms — delayed like ACH; intent may return without capability_token until funded

Stripe Connect (immediate)

When create returns capability_token (or capabilityToken), funding is complete:

paybond-session.ts

TS
TypeScript code sampleSwipe to inspect long lines
const intentId = created.intent_id;
const capabilityToken = created.capability_token;
if (!capabilityToken) {
  throw new Error("expected funded intent on stripe_connect");
}

ACH debit (delayed)

Create may return an intent without a capability token. Wait until Harbor reports funded, then read the token from intent state or fund retry helpers your integration layer provides. Do not run paid tools while the bank debit is pending.

x402 USDC (payment-session handshake)

Prefer paybond.intents.fundWithX402 (TypeScript) or paybond.intents.fund_with_x402 (Python) — one call that signs the 402 challenge, retries with payment-signature, and polls until capability_token is issued. Wallet keys stay in your app via injectable signers.

paybond-session.ts

TS
TypeScript code sampleSwipe to inspect long lines
const funded = await paybond.intents.fundWithX402({
  intentId,
  recognitionProof: await issueAgentRecognitionProofV1({
    purpose: "harbor.intent.fund",
    method: "POST",
    path: `/harbor/intents/${intentId}/fund`,
    body: {},
  }),
  signPayment: (challenge) => x402Wallet.signPayment(challenge),
  issueRecognitionProof: (envelope) =>
    issueAgentRecognitionProofV1({
      purpose: "harbor.intent.fund",
      method: envelope.method,
      path: envelope.path,
      body: envelope.body,
    }),
});

const capabilityToken = funded.capabilityToken;

See TypeScript quickstart — Stablecoin funding and Python quickstart for the advanced manual /fund loop and local WireMock/offline testing.

Stripe MPP (Payment Auth)

For stripe_mpp intents, Harbor returns 402 with WWW-Authenticate: Payment … challenges. Use fundWithMppCharge / fund_with_mpp_charge for one-shot Stripe charges, or fundWithMppSession / fund_with_mpp_session for Tempo session channel deposits. Kit sends credentials on x-paybond-payment-authorization through Gateway so Authorization: Bearer stays available for tenant auth.

See Fund intents on Stripe MPP for charge vs session selection, the full header flow, sandbox dual-challenge behavior, and tenant-isolation warnings. Quickstarts: TypeScript MPP funding and Python MPP funding.

Flutterwave Virtual Account (delayed)

For flutterwave_virtual_account intents, create may return VA funding instructions without a capability_token. A payer sends a bank transfer into the tenant-owned Virtual Account; Harbor moves to funded only after Paybond verifies the VA credit webhook (flutterwave-signature HMAC or legacy verif-hash). Do not run paid tools while the transfer is pending.

Intent budget currency must match the destination corridor (NGN or GHS). Terminal release/refund is async — Transfer payout or refund webhooks finalize released / refunded, not the Transfer API response alone.

Setup: Configure Flutterwave settlement. Production integration context: Settlement with payment providers.

Step 3 — Authorize spend before tool work

Capabilities are intent-scoped credentials — not API keys. Paybond mints them at funded; there is no separate issuance endpoint.

paybond-session.ts

TS
TypeScript code sampleSwipe to inspect long lines
const guard = paybond.spendGuard(intentId, capabilityToken);
await guard.authorizeSpend({
  operation: "travel.book_hotel",
  requestedSpendCents: 20_000,
});

paybond_session.py

PY
Python code sampleSwipe to inspect long lines
guard = paybond.spend_guard(intent_id, capability_token)
await guard.authorize_spend(
    operation="travel.book_hotel",
    requested_spend_cents=20_000,
)

For multi-tool agents, prefer agent middleware (PaybondAgentRun and PaybondToolRegistry) so every side-effecting tool shares one intent and auto-evidence.

Wrap handlers with guardTool / guard_tool or call authorizeSpend immediately before vendor API calls.

For stripe_mpp session intents, POST /verify may also require a Tempo voucher credential (mpp_voucher_required until supplied). Cumulative voucher spend is capped at the signed intent amount_cents; only one pending voucher may be in flight per intent. See Session voucher metering at verify.

After funding — evidence and settlement

Funding authorizes spend up to the intent budget. It does not release money to the payee.

  1. Run the guarded tool and collect completion fields (API status, vendor refs, signed receipts — not funding webhook payloads).
  2. Submit evidence via paybond.intents.submitEvidence / submit_evidence.
  3. Harbor evaluates the completion rule and confirms release or refund.

See Completion presets — Funding vs completion and How agent settlement works.

Rail-specific integration checklists

stripe_connect

  1. Confirm settlement console shows linked Connect destination and allowed rail.
  2. Create intent with settlementRail: "stripe_connect".
  3. Read capability_token from create when funded.
  4. Guard tool → submit api_response_ok, invoice_payment_confirmed, or another matching preset evidence.

stripe_ach_debit

  1. Confirm ACH capability is ready in settlement console.
  2. Optionally link a Plaid Auth bank (Instant Auth / Instant Match / AMD) — Configure Plaid bank verification — or use Stripe Financial Connections at fund time.
  3. Create intent with settlement_rail: "stripe_ach_debit".
  4. Fund with a ready plaid_bank_account_id when using Plaid, or complete the Financial Connections path when not.
  5. Wait for funded after Stripe confirms the bank debit (payment_intent.succeeded).
  6. Guard tool → submit ach_paid_api_ok or matching ACH preset evidence.

Confirm Plaid readiness with paybond plaid ready / paybond plaid doctor when using the Plaid path.

x402_usdc_base

  1. Confirm Base receive address is saved in tenant config.
  2. Create intent with settlementRail: "x402_usdc_base" (budget still USD cents).
  3. Complete /fund handshake until authorization_succeeded.
  4. Guard tool → submit x402_paid_api_ok, x402_delivery_receipt, x402_cost_and_completion, x402_saas_api_purchase, or x402_travel_booking.

stripe_mpp

  1. Confirm MPP readiness in settlement console (Harbor MPP runtime required for production).
  2. Create intent with settlementRail: "stripe_mpp" (budget must be USD-denominated for MVP).
  3. Call fundWithMppCharge for one-shot charges or fundWithMppSession for Tempo session channel deposits.
  4. Guard tool → submit completion evidence matching your workflow preset after capability_token is issued.

Full MPP checklist, header contract, and isolation rules: Fund intents on Stripe MPP.

flutterwave_virtual_account

  1. Confirm Flutterwave destination (secret key and webhook secret) and allowed rail in settlement console — start in sandbox.
  2. Create intent with settlementRail: "flutterwave_virtual_account" and matching corridor currency (NGN or GHS).
  3. Present VA funding instructions to the payer; wait for funded after the VA credit webhook confirms.
  4. Guard tool → submit completion evidence matching your workflow preset after capability_token is issued.

Setup walkthrough: Configure Flutterwave settlement.

paystack_nip

  1. Confirm the Paystack destination (secret key plus DVA account_number or va_id) and allowed rail in Console Settlement — start in sandbox.
  2. Create an NGN intent with settlementRail: "paystack_nip".
  3. Present DVA funding instructions to the payer; wait for funded after the signed charge.success webhook confirms.
  4. Guard the tool, then submit completion evidence after the capability token is issued.

Paystack uses the tenant's single vaulted secret key for both API authentication and fail-closed X-Paystack-Signature HMAC-SHA512 webhook verification. Terminal Transfer (NIP) settlement remains pending until its signed lifecycle webhook confirms. Setup walkthrough: Configure Paystack settlement.

Common questions

Why did create not return a capability token?

The rail may be delayed (stripe_ach_debit, x402_usdc_base, stripe_mpp, flutterwave_virtual_account) or funding failed. Inspect intent state in the operator console or Harbor API before retrying tool calls.

Can I reuse a capability across intents?

No. Capability tokens are bound to one intent_id and minted when that intent reaches funded.

Is funding the same as releasing to the payee?

No. Funding escrow-authorizes spend. Release happens after evidence passes the intent's completion rule and settlement is confirmed.

What about Stripe MPP (Machine Payments Protocol)?

stripe_mpp is a valid settlement rail literal across Harbor, Gateway, and Kit. See Fund intents on Stripe MPP for charge vs session selection, Payment Auth headers, sandbox behavior, and tenant boundaries. Also: stripe_mpp support matrix row. Use x402_usdc_base or stripe_connect for production agent spend until your tenant's MPP readiness checks pass.

Where to go next