Skip to main content
A Payment Intent represents a single payment request. It tracks the full lifecycle from creation through on-chain settlement.

Schema

Each Payment Intent includes:
FieldTypeDescription
idstringUnique ID, prefixed with pi_
chainstringCAIP-2 chain identifier
tokenstringCanonical symbol (USDC) or chain-specific address
amountstringDecimal amount (e.g. "10.50")
requestorstringWallet address requesting payment
fulfillerstring | nullWallet address fulfilling payment
directionstringrequest (requestor created) or send (fulfiller pushes)
statestringCurrent lifecycle state
referencestringOn-chain correlation key
metadataobject | nullCustom key-value pairs (max 20 keys)
See the API reference for the complete schema.

State machine

Payment Intents follow a strict state machine:
created ──→ pending ──→ confirmed ──→ finalized
  │            │            │
  │            │            └── (background finality)
  │            ├──→ failed
  │            └──→ expired*

  └──→ cancelled
StateMeaning
createdIntent exists, no transaction submitted
pendingSigned transaction broadcast to chain, awaiting confirmation
confirmedSufficient confirmations — this is the user-facing completion signal
finalizedChain-level finality (background signal)
failedOn-chain failure (revert, program error)
expiredTTL elapsed without fulfillment
cancelledExplicitly 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 expired with pendingAtExpiry: true.
  • Dropped transactions (Solana): Solana transactions expire after ~60 blockhashes (~60s). If Cherp detects that a transaction was dropped, it resets the intent to created with retryRequired: true. The SDK surfaces a re-sign prompt.
  • Cancellation: Only allowed from the created state, 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)
After the TTL elapses, unconfirmed intents transition to expired.

Idempotency

Creating an intent with the same idempotencyKey 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 calling POST /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.