Tour of the API Fresh
See how Stripe API objects fit together and learn best practices for combining them.
Core concepts
Everything is an object
Everything in your Stripe account is an object, whether you create it with the API or not. Your balance corresponds to a Balance object, you track recurring customer charges with Subscription objects, you store payment details in PaymentMethod objects, and so on.
Even low-code and no-code integrations produce these objects. So do actions you perform in the Dashboard. When you manually create a product in the Dashboard, it creates a Product object in the API.
Objects have lives (state machines)
The API uses a single object to track each process. You create the object at the start of the process, and after every step you can check its status to see what needs to happen next.
For instance, while completing a payment, a customer might try several payment methods. If one fails, a status of requires_payment_method tells you to prompt the customer for another.
An integration is made of cooperating objects
To accept a payment, a system creates several core objects and manages them through several states. Your integration is a system that handles this creation and management by communicating with Stripe.
Payment objects
Stripe uses a variety of related objects to facilitate payments.
PaymentIntent
A PaymentIntent represents your intent to collect a payment. It tracks a payment from creation through checkout and triggers additional authentication steps when required.
Statuses a PaymentIntent flows through:
| Status | Meaning |
|---|---|
requires_payment_method | Waiting for payment details |
requires_confirmation | Waiting for customer to confirm |
requires_action | Requires additional auth (e.g., 3D Secure) |
processing | Stripe is processing the payment |
succeeded | Payment complete |
canceled | Payment was canceled |
bash
# Create a PaymentIntent
curl https://api.stripe.com/v1/payment_intents \
-u "sk_test_YOUR_KEY:" \
-d amount=2000 \
-d currency=usdPaymentMethod
A PaymentMethod stores payment details (card number, wallet token, bank account). Stripe uses it to make the actual charge.
bash
curl https://api.stripe.com/v1/payment_methods \
-u "sk_test_YOUR_KEY:" \
-d type=card \
-d "card[number]=4242424242424242" \
-d "card[exp_month]=12" \
-d "card[exp_year]=2034" \
-d "card[cvc]=123"Customer
A Customer object lets you reuse payment methods, track payment history, and attach subscriptions.
bash
curl https://api.stripe.com/v1/customers \
-u "sk_test_YOUR_KEY:" \
-d email="customer@example.com"Charge
A Charge is created when a PaymentIntent is confirmed. It represents the specific attempt to move money. If a charge fails, the PaymentIntent allows retrying with new payment details without creating a new PaymentIntent.
Event
Event objects represent activity in your account — "the charge succeeded", "the subscription was canceled", "the invoice payment failed." You respond to events using webhooks.
json
{
"id": "evt_1234",
"type": "payment_intent.succeeded",
"data": {
"object": { "id": "pi_abc", "amount": 2000, "status": "succeeded" }
}
}The path to a payment
- Customer clicks Checkout — your server creates a
PaymentIntentfor the cart total - Customer enters payment details — Stripe.js collects them and creates a
PaymentMethod, or Checkout handles this - Customer clicks Pay — the
PaymentIntentis confirmed - Stripe processes the payment — status moves to
processing, thensucceededor back torequires_payment_method - You fulfill the order — listen for the
payment_intent.succeededwebhook
Key integration patterns
One-time payment (Checkout)
Simplest path. Redirect to Stripe-hosted checkout page. Stripe handles all UI, 3DS, confirmation.
javascript
// Server: create a Checkout Session
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: [{ price: 'price_xyz', quantity: 1 }],
mode: 'payment',
success_url: 'https://example.com/success',
cancel_url: 'https://example.com/cancel',
})
// Redirect to session.urlCustom payment form (Payment Element)
Use Stripe's Payment Element embedded in your own page. Full UI control, all payment methods.
javascript
// Client: mount the Payment Element
const elements = stripe.elements({ clientSecret })
const paymentElement = elements.create('payment')
paymentElement.mount('#payment-element')Subscriptions
Create a Subscription linking a Customer to a Price. Stripe auto-generates invoices and charges on each billing cycle.
Saving a card for later
Use SetupIntent to collect and verify a payment method without charging. Attach the resulting PaymentMethod to a Customer for future use.
Object relationships
Customer
└── PaymentMethods (attached)
└── Subscriptions
└── Invoices
└── PaymentIntents
└── Charges
PaymentIntent (standalone one-time payment)
└── PaymentMethod
└── Charge
└── EventsBest practices
- Create PaymentIntents early — as soon as the customer starts checkout. Update the amount if it changes.
- Reuse PaymentIntents — if checkout is interrupted, retrieve and reuse the same PaymentIntent rather than creating a new one.
- Use idempotency keys — pass
Idempotency-Keyheaders to prevent duplicate operations on retries. - Handle webhooks — don't rely solely on redirect URLs for fulfillment. Webhooks are the authoritative signal.
- Store object IDs — save
PaymentIntent.id,Customer.id, etc. in your database. You'll need them to retrieve and update objects.