Payments
PerfectPay's payment flow works in three steps:
- Create the payment on the server
- Collect or select a payment method on the client (or server)
- Confirm the payment and react to the resulting status
Payment Flow
Loading diagram...
Create a Payment
POST /payments
GET //sandbox.perfectpay.ai/payments
curl https://sandbox.perfectpay.ai/payments \
-X POST \
-H "api-key: YOUR_SECRET_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 4999,
"currency": "USD",
"customer_id": "cus_abc123",
"capture_method": "automatic",
"authentication_type": "no_three_ds",
"return_url": "https://example.com/checkout/complete",
"confirm": false,
"description": "Order 1001",
"metadata": {
"order_id": "1001"
}
}'
Response excerpt:
JSON
{
"payment_id": "pay_mbabizu24mvu3mela5njyhpit4",
"client_secret": "pay_mbabizu24mvu3mela5njyhpit4_secret_abc123",
"amount": 4999,
"currency": "USD",
"status": "requires_payment_method"
}
Set "confirm": true along with payment_method_data to create and confirm in a single call.
Confirm a Payment
POST /payments/{payment_id}/confirm
GET //sandbox.perfectpay.ai/payments/pay_mbabizu24mvu3mela5njyhpit4/confirm
curl https://sandbox.perfectpay.ai/payments/pay_mbabizu24mvu3mela5njyhpit4/confirm \
-X POST \
-H "api-key: YOUR_SECRET_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"payment_method": "card",
"payment_method_type": "credit",
"payment_method_data": {
"card": {
"card_number": "4242424242424242",
"card_exp_month": "10",
"card_exp_year": "25",
"card_cvc": "123",
"card_holder_name": "Jane Doe"
}
}
}'
Use raw card data in sandbox or controlled PCI environments only. For production browser flows, use the Web SDK.
Capture a Payment
For payments created with "capture_method": "manual", you must explicitly capture after authorization succeeds.
POST /payments/{payment_id}/capture
GET //sandbox.perfectpay.ai/payments/pay_mbabizu24mvu3mela5njyhpit4/capture
curl https://sandbox.perfectpay.ai/payments/pay_mbabizu24mvu3mela5njyhpit4/capture \
-X POST \
-H "api-key: YOUR_SECRET_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount_to_capture": 4999
}'
Cancel a Payment
POST /payments/{payment_id}/cancel
GET //sandbox.perfectpay.ai/payments/pay_mbabizu24mvu3mela5njyhpit4/cancel
curl https://sandbox.perfectpay.ai/payments/pay_mbabizu24mvu3mela5njyhpit4/cancel \
-X POST \
-H "api-key: YOUR_SECRET_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"cancellation_reason": "requested_by_customer"
}'
Retrieve a Payment
GET /payments/{payment_id}
GET //sandbox.perfectpay.ai/payments/pay_mbabizu24mvu3mela5njyhpit4
curl https://sandbox.perfectpay.ai/payments/pay_mbabizu24mvu3mela5njyhpit4 \
-H "api-key: YOUR_SECRET_API_KEY"
List Payments
GET /payments/list
GET //sandbox.perfectpay.ai/payments/list
curl https://sandbox.perfectpay.ai/payments/list \
-H "api-key: YOUR_SECRET_API_KEY"
Payment Status Values
| Status | Meaning |
|---|---|
requires_payment_method | Payment exists but no usable method is attached |
requires_confirmation | Method is attached but confirmation has not happened |
requires_customer_action | The customer must complete a redirect or 3DS step |
processing | The processor has accepted the request and final settlement is pending |
requires_capture | Authorization succeeded and manual capture is required |
succeeded | Charge completed successfully |
failed | The attempt failed |
partially_captured | Part of the authorized amount has been captured |
partially_captured_and_capturable | Part captured, remaining amount still capturable |
expired | The payment timed out |
Common next_action Types
When a payment requires customer action, the response includes a next_action object. The most common types are:
| Type | What to do |
|---|---|
redirect_to_url | Send the customer to the processor or issuer redirect |
three_ds_invoke | Render or complete a 3DS flow |
third_party_sdk_session_token | Hand the wallet or third-party SDK the returned token |
display_bank_transfer_information | Show the returned bank transfer instructions |
qr_code_information | Display the returned QR image or URL |
fetch_qr_code_information | Poll the returned URL for fresh QR data |