Payment Intents
A payment intent tracks one payment from creation to a terminal state. Mockpay mirrors Stripe's shape and lifecycle. No money moves; every outcome is simulated from test payment method tokens.
Lifecycle
requires_payment_method → requires_confirmation → confirm
capture_method=automatic → succeeded
capture_method=manual → requires_capture → capture → succeeded
any pre-terminal state → cancel → canceled
declined confirm → requires_payment_method (retryable, last_payment_error set)Endpoints
| Method | Path | Action |
|---|---|---|
POST | /v1/payment_intents | Create (optionally confirm in the same call) |
GET | /v1/payment_intents | List, newest first. limit 1–100 (default 10), starting_after cursor, has_more flag |
GET | /v1/payment_intents/:id | Retrieve |
POST | /v1/payment_intents/:id | Update. amount, currency, payment_method change only before confirmation; metadata merges (empty string removes a key) |
POST | /v1/payment_intents/:id/confirm | Confirm with a test payment method |
POST | /v1/payment_intents/:id/capture | Capture a requires_capture intent, in full or via amount_to_capture |
POST | /v1/payment_intents/:id/cancel | Cancel with optional cancellation_reason: abandoned, duplicate, fraudulent, requested_by_customer |
Create parameters
amount(required): positive integer in the smallest currency unit, max 99999999.currency(required): three-letter ISO code, stored lowercase.capture_method:automatic(default) ormanual.payment_method: test token (pm_...). Attaching moves status torequires_confirmation.confirm:trueconfirms in the same call; requirespayment_method.description,metadata: freeform.
Bodies are JSON or form-encoded.
Test payment methods
| Token | Outcome |
|---|---|
pm_card_visa, pm_card_mastercard, pm_card_amex, any unreserved pm_ token | Succeeds |
pm_card_chargeDeclined | 402 card_error / card_declined / generic_decline |
pm_card_chargeDeclinedInsufficientFunds | 402 card_error / card_declined / insufficient_funds |
A decline persists last_payment_error on the intent, detaches the payment method, and returns status to requires_payment_method. The intent stays retryable. The 402 body carries the full intent under error.payment_intent.
Errors
The /v1 lane answers errors in the Stripe shape: { "error": { "type", "code", "message" } }. Types: invalid_request_error (400, 401, 404), card_error (402), api_error (500). Unknown resources answer 404 with code: "resource_missing"; cross-account ids are indistinguishable from missing ids.
Example
curl https://api.mockpay.net/v1/payment_intents \
-u mock_sk_51H8sandbox...: \
-d amount=2000 \
-d currency=usd \
-d payment_method=pm_card_visa \
-d confirm=trueResponds 200 with "status": "succeeded" and "amount_received": 2000.
Retention
Payment intents expire 365 days after creation. Updates never extend expiry. Platform records (accounts, keys) never expire.