#Card payments
Create a card payment with POST /v1/transactions (alias: POST /v1/payment-intents — identical behavior). All amounts are integers in cents. A 3% platform fee is applied automatically to charges routed to your connected account.
#Create a payment
| Field | Type | Required | Description |
|---|---|---|---|
amount |
integer | ✔ | Amount in cents. Minimum 50. |
currency |
string | ISO 3-letter code. Defaults to your account currency. | |
payment_method |
string | A processor payment-method id to charge immediately. | |
payment_method_type |
string | One of card, wallet, bank_transfer, ach, terminal. Defaults to card. |
|
confirm |
boolean | Confirm immediately (requires payment_method). Default false. |
|
capture_method |
string | automatic (default) or manual (authorize now, capture later). |
|
customer_id |
uuid | An existing PlutoPay customer. | |
description |
string | Appears on the transaction and receipts. | |
receipt_email |
string | Email to send a receipt to. | |
return_url |
string | Redirect target after off-session confirmation. | |
metadata |
object | Arbitrary key/value pairs echoed back on the object and in webhooks. |
Pass an Idempotency-Key header to make creation safely retryable.
curl https://plutopayus.com/api/v1/transactions \
-H "Authorization: Bearer sk_test_your_key_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order_1001" \
-d '{
"amount": 4750,
"currency": "usd",
"payment_method_type": "card",
"description": "Order #1001",
"receipt_email": "customer@example.com",
"metadata": { "order_id": "1001" }
}'
#Response 201
{
"data": {
"id": "019c8044-2ab5-7396-b5af-216ef14dc582",
"reference": "txn_8f3kQ2mZ0pLxWvA1bC9d",
"type": "payment",
"status": "pending",
"amount": 4750,
"amount_refunded": 0,
"currency": "usd",
"payment_method_type": "card",
"description": "Order #1001",
"receipt_email": "customer@example.com",
"source": "api",
"is_test": true,
"metadata": { "order_id": "1001" },
"created_at": "2026-07-05T14:12:03+00:00",
"updated_at": "2026-07-05T14:12:03+00:00"
},
"client_secret": "pi_3T2..._secret_9Yx..."
}
The response also includes
status_badge, and (for card payments)card_brand/card_last_four. Timestamp fieldscaptured_at,failed_at,refunded_at,disputed_atpopulate as the transaction moves through those states.
#Confirming on the client
Use the client_secret on the client (with your publishable key) to confirm the payment with Stripe.js’ Payment Element — mounted on your own page, so the card never touches your server. This is the Elements integration from Choosing an integration.
const stripe = Stripe('pk_test_your_key_here');
const elements = stripe.elements({ clientSecret });
elements.create('payment').mount('#payment-element');
// on submit:
await stripe.confirmPayment({ elements, confirmParams: { return_url } });
The final state arrives by webhook — payment.succeeded or payment.failed.
#Capture, cancel, retrieve
POST /v1/transactions/{id}/capture # for capture_method: "manual"
POST /v1/transactions/{id}/cancel # cancel an uncaptured payment
GET /v1/transactions/{id}
GET /v1/transactions?status=succeeded&page=1&per_page=20
#Refund
POST /v1/transactions/{transaction}/refunds
| Field | Type | Description |
|---|---|---|
amount |
integer | Amount in cents to refund. Defaults to the full refundable balance. |
reason |
string | Optional reason. |
Refunds on connected-account charges automatically reverse the transfer and the application fee, so the refund cost lands on the correct account. A full refund sets the transaction status to refunded; a partial refund sets partially_refunded.
Next: Hosted checkout & links · Webhooks