Schema
Each Payment Intent includes:| Field | Type | Description |
|---|---|---|
id | string | Unique ID, prefixed with pi_ |
chain | string | CAIP-2 chain identifier |
token | string | Canonical symbol (USDC) or chain-specific address |
amount | string | Decimal amount (e.g. "10.50") |
requestor | string | Wallet address requesting payment |
fulfiller | string | null | Wallet address fulfilling payment |
direction | string | request (requestor created) or send (fulfiller pushes) |
state | string | Current lifecycle state |
reference | string | On-chain correlation key |
metadata | object | null | Custom key-value pairs (max 20 keys) |
State machine
Payment Intents follow a strict state machine:| State | Meaning |
|---|---|
created | Intent exists, no transaction submitted |
pending | Signed transaction broadcast to chain, awaiting confirmation |
confirmed | Sufficient confirmations — this is the user-facing completion signal |
finalized | Chain-level finality (background signal) |
failed | On-chain failure (revert, program error) |
expired | TTL elapsed without fulfillment |
cancelled | Explicitly cancelled before fulfillment |
Important behaviors
- Expired with pending tx: If a transaction is in the mempool when TTL expires, a 10-minute grace period is granted. If confirmed within grace, normal flow continues. Otherwise the intent is marked
expiredwithpendingAtExpiry: true. - Dropped transactions (Solana): Solana transactions expire after ~60 blockhashes (~60s). If Cherp detects that a transaction was dropped, it resets the intent to
createdwithretryRequired: true. The SDK surfaces a re-sign prompt. - Cancellation: Only allowed from the
createdstate, before any transaction is submitted.
Direction
Payment Intents support two directions:request(default) — The requestor creates the intent and the fulfiller pays. This is the typical merchant or P2P “request money” flow.send— The fulfiller creates the intent and pushes payment. This is the “send money” flow.
TTL and expiry
Every intent has a TTL (time-to-live):- Default: 86,400 seconds (24 hours)
- Minimum: 300 seconds (5 minutes)
- Maximum: 2,592,000 seconds (30 days)
expired.
Idempotency
Creating an intent with the sameidempotencyKey within 24 hours returns the existing intent instead of creating a duplicate. The response includes X-Idempotent-Replayed: true.
Refunds
You can create a linked refund intent by callingPOST /v1/intents/:id/refund. The refund intent goes through the same lifecycle as a regular intent. The original intent’s refundedBy field links to the refund, and the refund’s refundOf field links back.