Commerce first.Keep the order.
Payment APIs push commerce complexity onto your app. Flint keeps payments, checkout, refunds, and subscriptions connected through the same order model.
const intent = await flint.paymentIntents.create({ amountMoney: { amount: 2500, currency: "USD" }, paymentSourceToken: "pm_1Qs2...x4B", autoConfirm: true,})// intent.status === "SUCCEEDED"// Start simple. No order required.Compare
Payment acceptance is not the hard part.
The hard part starts after the charge: what was bought, how totals were computed, what changed, and how a refund maps back to the buyer experience. That is where payment primitives stop being enough.
1const cart = await db.cart.findUnique({2 where: { id: cartId },3 include: { items: true, customer: true },4})56if (!cart) throw new Error("Cart not found")1const subtotal = cart.items.reduce(2 (sum, item) => sum + item.price * item.qty, 03)4const tax = await taxService.calculate({5 amount: subtotal,6 address: cart.customer.address,7})1const session = await stripe.checkout.sessions.create({2 line_items: cart.items.map(toLineItem),3})45app.post("/webhook", async (req, res) => {6 // update your order, coupon usage, and status7})1const order = await flint.orders.create({2 lineItems: [3 { name: "Cold Brew", quantity: 2,4 unitPriceMoney: { amount: 650, currency: "USD" } },5 { name: "Croissant", quantity: 1,6 unitPriceMoney: { amount: 495, currency: "USD" } },7 ],8})1const checkout = await flint.checkoutSessions.create({2 orderId: order.orderId,3 redirects: {4 successRedirectUrl: "https://app.example/success",5 cancelRedirectUrl: "https://app.example/cart",6 },7})Why Teams Switch
The rewrite usually starts with edge cases.
Most teams do not replace their payment stack because the first charge fails. They replace it when support, reconciliation, and new buyer flows make the old model too expensive to keep together.
Line items, tax, discounts, and buyer context live in your app, while the charge lives somewhere else.
Flint keeps the order, checkout, and payment state on one record your team can actually read.
Support has to reconcile what the buyer bought, what they paid, and what got refunded across multiple systems.
Refunds attach to the same order record and activity trail instead of becoming isolated money movement.
Checkout, subscriptions, and future buyer workflows add more objects, webhooks, and sync logic to maintain.
Flint keeps new flows on the same API and order model instead of forcing a later rewrite.
Start simple. Grow without rewrites.
Adopt the order only when the product needs it.
Use Flint like a payment API on day one. The moment the product needs line items, checkout, refunds, or subscriptions, you keep building on the same model instead of introducing a second system.
Take a payment and move on.
If all you need is to charge a customer, Flint lets you do exactly that. One call. No order required. No forced complexity.
const intent = await flint.paymentIntents.create({ amountMoney: { amount: 2500, currency: "USD" }, paymentSourceToken: "pm_1Qs2...x4B", autoConfirm: true,})// intent.status === "SUCCEEDED"Real Workflow Example
One buyer flow. One order record.
The point is not that Flint can create a charge. The point is that the same record stays readable when the buyer pays, support steps in, and the product later grows onto the same order model.
Create the order once
Your app creates one order with line items, totals, buyer context, and the exact thing being sold before money moves.
Attach checkout and get paid
The buyer completes checkout, and the payment lands back on that same order instead of becoming a disconnected charge.
Handle the support moment
If the buyer needs a refund or a status explanation, support can act against the order instead of reconciling multiple systems.
Add the next workflow later
When the product expands into subscriptions or other commerce flows, it builds on the same order model instead of introducing a second system.
Recurring Billing
Subscription billing stays closer to what you actually sell.
Flint keeps recurring billing on top of the same order model. Multiple line items, trial terms, and lifecycle rules can live together instead of getting split across billing primitives.
const baseProduct = await stripe.products.create({ name: "Pro Platform",})const basePrice = await stripe.prices.create({ product: baseProduct.id, recurring: { interval: "month" },})const seatsProduct = await stripe.products.create({ name: "Team Seats",})const seatsPrice = await stripe.prices.create({ product: seatsProduct.id, recurring: { interval: "month" },})const sub = await stripe.subscriptions.create({ customer: "cus_xxx", items: [ { price: basePrice.id }, { price: seatsPrice.id, quantity: 5 }, ],})const plan = await flint.subscriptionPlans.create({ name: "Pro Platform + Seats", lineItems: [ { name: "Base platform", unitPriceMoney: { amount: 4900, currency: "USD" }, quantity: 1 }, { name: "Team seats", unitPriceMoney: { amount: 1800, currency: "USD" }, quantity: 5 }, ], billingInterval: "monthly", trialPeriodDays: 14,})const sub = await flint.subscriptions.create({ planId: plan.planId, customerId: "cus_01HZ4X...",})Developer Fit
Why teams keep this in production.
Teams do not just buy features. They buy systems they can trust under retries, refunds, support workflows, and product change.
API-first, not dashboard-first
The core model is available directly in the API and SDKs. The dashboard helps you operate it; it is not where the real system lives.
Less schema you own
You do not need to build and maintain separate cart, totals, coupon, and reconciliation tables before you can ship.
Operational safety
Deterministic statuses and explicit lifecycle state make retries, webhooks, refunds, and support flows easier to reason about.
Grows without a rewrite
Start with payments if you want. Add orders, checkout, refunds, and subscriptions later on the same API instead of rebuilding around a new model.
AI
The same order model is easier for agents and internal tools.
Flint returns explicit order, refund, and lifecycle state, plus method hints for side effects. Agents and support tools do better when they do not have to infer business context from raw charges.
Pricing
Start free. Move up when you need more.
Start in the sandbox, ship the first integration, and move to paid plans when you want lower fees, reporting, and production support.