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.
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.
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
});
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
| Rail | Typical funding path | capability_token timing |
|---|---|---|
stripe_connect | PaymentIntent authorized during create (or immediately after) | Often in the create response |
stripe_ach_debit | Bank debit initiated; Harbor waits for Stripe confirmation | After payment_intent.succeeded — may require waiting or polling |
x402_usdc_base | paybond.intents.fund x402 handshake on POST /harbor/intents/{id}/fund | After authorization succeeds on Base |
Stripe Connect (immediate)
When create returns capability_token (or capabilityToken), funding is complete:
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)
Kit wraps Harbor's 402 → sign → retry flow:
const fundProof = await issueAgentRecognitionProofV1({
purpose: "harbor.intent.fund",
method: "POST",
path: `/harbor/intents/${intentId}/fund`,
body: {},
});
let funded = await paybond.intents.fund({ intentId, recognitionProof: fundProof });
if (funded.statusCode === 402 && funded.paymentRequired) {
const paymentSignature = await x402Wallet.signPayment(funded.paymentRequired);
const retryProof = await issueAgentRecognitionProofV1({ /* same path */ });
funded = await paybond.intents.fund({
intentId,
recognitionProof: retryProof,
paymentSignature,
});
}
const capabilityToken = funded.capabilityToken;
See TypeScript quickstart — Stablecoin funding and Python quickstart for full signing helpers.
MCP hosts
Use paybond_create_spend_intent and paybond_fund_intent over stdio MCP, then pass the returned intent_id and capability_token to paybond_authorize_agent_spend before side-effecting tools.
Step 3 — Authorize spend before tool work
Capabilities are intent-scoped credentials — not API keys. Harbor mints them at funded; there is no separate issuance endpoint.
const guard = paybond.spendGuard(intentId, capabilityToken);
await guard.authorizeSpend({
operation: "travel.book_hotel",
requestedSpendCents: 20_000,
});
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 + 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.
After funding — evidence and settlement
Funding authorizes spend up to the intent budget. It does not release money to the payee.
- Run the guarded tool and collect completion fields (API status, vendor refs, signed receipts — not funding webhook payloads).
- Submit evidence via
paybond.intents.submitEvidence/submit_evidence. - Harbor evaluates the predicate and confirms release or refund.
See Completion presets — Funding vs completion and How agent settlement works.
Rail-specific integration checklists
stripe_connect
- Confirm settlement console shows linked Connect destination and allowed rail.
- Create intent with
settlementRail: "stripe_connect". - Read
capability_tokenfrom create when funded. - Guard tool → submit
api_response_okor matching preset evidence.
stripe_ach_debit
- Confirm ACH capability is ready in settlement console.
- Create intent with
settlement_rail: "stripe_ach_debit". - Wait for
fundedafter bank debit confirms. - Guard tool → submit
ach_paid_api_okor matching ACH preset evidence.
x402_usdc_base
- Confirm Base receive address is saved in tenant config.
- Create intent with
settlementRail: "x402_usdc_base"(budget still USD cents). - Complete
/fundhandshake untilauthorization_succeeded. - Guard tool → submit
x402_paid_api_ok,x402_delivery_receipt, orx402_cost_and_completion.
Common questions
Why did create not return a capability token?
The rail may be delayed (stripe_ach_debit, x402_usdc_base) 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 predicate and settlement is confirmed.