Payment Flow
What You’ll LearnThis guide covers:
- The complete payment lifecycle (Fund → Card → Spend → Settle)
- Card credential access and attestation
- Intent declaration flow for controlled spending
- Transaction states and webhook events
- Common scenarios and timing considerations
Overview
The LedgerOS payment system follows a secure flow:Phase 1: Setup
User Onboarding
Before any spending can happen, you need a verified, funded user:1
Create User
user_id2
Initiate KYC
verificationUrl - send this to your user3
User Completes KYC
User visits the verification URL and completes identity verification.
You receive webhook:
user.approved when complete.4
User Deposits Funds
deposit.completed when funds are credited.Agent Creation
Once a user is funded, register agents:agent_id and optionally an agent_token for agent-scoped API access.
Phase 2: Purchase Flow
Card Creation
Create a card for the specific purchase:| Parameter | Description |
|---|---|
purpose | Human-readable description (for audit) |
type | single (one transaction) or multi (reusable with limits) |
maxAmount | Maximum spend in cents |
Intent Declaration
Before accessing card credentials, agents must declare their spending intent:Card Detail Access (Attestation)
When your agent needs the actual card credentials:Attestation Creates Audit TrailThe
accessEventId links this credential access to your stated intent. When a transaction occurs, LedgerOS correlates it with the attestation to detect anomalies.Transaction Authorization
When the agent uses the card at a merchant:Phase 3: Settlement
Transaction States
| State | Description | Timing |
|---|---|---|
pending | Authorization approved, funds held | Immediate |
settled | Merchant captured, funds transferred | 1-3 business days |
voided | Merchant cancelled before settlement | Varies |
refunded | Merchant refunded after settlement | Varies |
Webhooks
You’ll receive webhooks for each state change:| Event | When |
|---|---|
transaction.created | Authorization approved |
transaction.settled | Funds captured |
transaction.voided | Authorization reversed |
transaction.refunded | Refund processed |
transaction.declined | Authorization denied |
Intent Matching
When a transaction occurs, LedgerOS matches it against the declared intent: Intent states after transaction:| State | Meaning |
|---|---|
matched | Transaction matches declared intent |
mismatched | Amount or merchant differs significantly |
expired | No transaction within 24 hours |
Card Lifecycle
Single-Use Cards
Single-use cards automatically close after one successful transaction settles.Multi-Use Cards
Multi-use cards remain open for repeat purchases until manually closed or limits are exceeded.Timing Considerations
| Stage | Typical Timing |
|---|---|
| KYC approval | 1-5 minutes (automated) |
| Crypto deposit credit | 2-5 minutes |
| Card creation | Instant |
| Authorization | < 2 seconds |
| Settlement | 1-3 business days |
Troubleshooting
Card details request fails with 'Declare intent first'
Card details request fails with 'Declare intent first'
Cause: No intent was declared for this card.Solution: Call
POST /v1/cards/{id}/intents before requesting details. All cards require intent declaration.Transaction declined: Insufficient balance
Transaction declined: Insufficient balance
Cause: User’s available balance is less than the transaction amount.Solution: Check balance with
GET /v1/balances/{userId}. User needs to deposit more funds.Transaction declined: Limit exceeded
Transaction declined: Limit exceeded
Cause: Transaction exceeds card’s per-transaction, daily, or monthly limit.Solution: Check card limits with
GET /v1/cards/{cardId}. Either increase limits or create a new card.Intent shows 'mismatched' after transaction
Intent shows 'mismatched' after transaction
Cause: Transaction amount or merchant differs significantly from declared intent.Solution: This is informational—the transaction still completes. Review the mismatch for potential issues. Consider adjusting intent parameters for future purchases.
Webhook not received
Webhook not received
Cause: Webhook endpoint unreachable or returned error.Solution: Check webhook logs in dashboard. Verify endpoint is accessible and returns 2xx. LedgerOS retries failed webhooks with exponential backoff.