Quick Start¶
This guide walks you through issuing your first LedgerFlow warrant and verifying an x402 payment with authorization.
Prerequisites¶
Step 1: Install¶
Step 2: Generate Keys¶
Generate an issuer key pair and an agent key pair:
# Generate issuer key (Ed25519)
cargo run -p ledgerflow-cli -- gen-key --label issuer
# Generate agent key (Ed25519)
cargo run -p ledgerflow-cli -- gen-key --label agent
Step 3: Issue a Warrant¶
Create a warrant authorizing the agent to make payments:
cargo run -p ledgerflow-cli -- issue-warrant \
--issuer-keys issuer.key \
--agent-keys agent.key \
--merchant "api.example.com" \
--max-amount 10.00 \
--asset USDC \
--ttl 3600 \
--tools "web_search,code_execution"
This creates a warrant that:
- Is signed by the issuer
- Authorizes the agent identified by
agent.key - Restricts to merchant
api.example.com - Limits spending to $10 USDC per request
- Expires in 1 hour
- Restricts to
web_searchandcode_executiontools
Step 4: Build the x402 Payment¶
When the agent receives an x402 402 Payment Required response:
cargo run -p ledgerflow-cli -- build-payment \
--warrant warrant.cbor \
--agent-keys agent.key \
--challenge-id "01HV7W8M7BX3Q6P0WJ7T5QK1V2" \
--accepted-hash "sha256:abc123..." \
--request-hash "sha256:def456..."
This produces the x402 payment payload with the LedgerFlow extension attached.
Step 5: Verify (Merchant Side)¶
The merchant middleware verifies the authorization:
Verification checks:
- Warrant signature validity
- Proof signature validity
- Warrant temporal validity
- Audience scope
- All constraints
- Proof binding
- Replay protection
Programmatic Usage¶
Issue a Warrant¶
use ledgerflow_core::{Warrant, SignerRef, Constraint};
let warrant = Warrant::builder()
.issuer(issuer_signer)
.subject_signer(agent_signer)
.payment_subjects(vec![payment_subject])
.audience(AudienceScope::MerchantIds(vec!["api.example.com".into()]))
.not_before(now_ms)
.expires_at(now_ms + 3600_000)
.delegation(DelegationPolicy { can_delegate: true, max_depth: 2 })
.constraints(vec![
Constraint::Merchant(MerchantConstraint {
host_suffixes: vec![".example.com".into()],
..Default::default()
}),
Constraint::Payment(PaymentConstraint {
max_per_request: AmountLimit { amount: "10000000".into(), asset: "USDC".into() },
..Default::default()
}),
])
.sign(&issuer_key)?;
Verify Authorization¶
use ledgerflow_x402::{verify_authorization, VerifierContext};
let ctx = VerifierContext::new()
.with_challenge_id(challenge_id)
.with_request(request)
.with_accepted(accepted);
let result = verify_authorization(&extension, &ctx)?;
match result {
AuthzResult::Authorized { warrant_id, .. } => {
// Proceed with x402 settlement
}
AuthzResult::Denied { reason, .. } => {
// Reject the payment
}
}
Integration Patterns¶
Pattern 1: Gateway Middleware¶
Place LedgerFlow verification in your x402 middleware layer:
Pattern 2: Sidecar¶
Run LedgerFlow verification as a sidecar service:
Pattern 3: MCP Proxy¶
For Model Context Protocol integrations, verify at the MCP proxy layer:
Testing¶
Run the acceptance scenarios:
Next Steps¶
- Core Concepts — Understand warrants, constraints, and delegation
- x402 Integration — Deep dive into x402 extension fields
- Constraints — Full constraint type reference
- Security — Threat model and replay protection