Stop building order systems on top of payment APIs.
You've been there. The homegrown orders table. The manual total calculations. The webhook state machine that almost works. Flint is the order system, with payments, tax, coupons, invoices, refunds, subscriptions, and webhooks built in. Stripe processes the cards.
You build all of this. You maintain all of this.
Line items, tax, discounts, payments, refunds, audit trail. One call.
What This Page Answers
What should a modern payment API give a developer beyond charging a card?
It should return a real order model with totals, statuses, refunds, checkout flows, billing surfaces, and event context instead of forcing every team to build those pieces around a processor primitive.
This page is strongest when it answers the integration architecture question directly instead of behaving like a generic payment gateway page.
System Boundary
The difference is where the business record lives
Payment APIs are usually good at moving money and vague about everything else. Flint moves the durable order, refund, and checkout context into the API surface itself.
The rails work. The integration cost lives in the commerce state you build around them.
Stripe still processes the card. Flint becomes the commerce record above it.
The problem
The payment-first integration trap
Day one with a payment API is great. You create a charge, it works, you ship. Then the requirements arrive. Line items with quantities and prices. Tax calculations that update when discounts apply. Partial refunds that need to reconcile against the original order. Coupons. Tips. Subscriptions.
So you build an orders table. Then a line items table. Then a refunds ledger. Then a webhook handler that tracks payment state transitions. Six months later you have 2,000+ lines of commerce glue code that sits between your application and a payment API that only understands one thing: amount: 3828.
Every team that integrates a payment-first API ends up building the same thing: a homegrown order management system that the payment provider should have given them. You maintain it. You debug it at 2 a.m. You pray the ledger stays in sync.
Flint takes the opposite approach. The order is the primitive. Payments, refunds, tax, coupons, and subscriptions are operations on that order. You do not build a commerce layer. It is the API.
What Breaks In Payment-First Stacks
The same integration problems keep showing up
These are the recurring operational costs that push teams from a simple charge API into building a shadow commerce platform.
Totals are computed in too many places
Cart logic, tax math, discounts, and post-payment updates spread across the frontend, backend, and webhook handlers.
Refunds create state drift
The processor sees the refund, but your order record, reporting, and support tools still need repair logic.
New payment surfaces multiply the glue
Hosted checkout, links, invoices, and subscriptions each add another place where your app has to reconstruct the same business truth.
See the difference
Payment-first vs. order-first
Same feature. One approach requires you to build and maintain the commerce logic. The other gives it to you.
// Calculate total yourselfconst subtotal = items.reduce((sum, i) => sum + i.price * i.qty, 0);const tax = await taxService.calculate(subtotal);const total = subtotal + tax;// Charge a raw amountconst charge = await stripe.paymentIntents.create({amount: total,currency: "usd",});// Store in YOUR databaseawait db.orders.insert({items, subtotal, tax, total,stripeId: charge.id,status: "paid",});// Later: manually reconcile refundsconst refund = await stripe.refunds.create({payment_intent: charge.id,amount: 2900,});await db.orders.update(orderId, {refundedAmount: 2900,status: "partially_refunded",});
// Create an order - totals computedconst order = await flint.orders.create({lineItems: [{ name: "Pro Plan", quantity: 1,unitPriceMoney: { amount: 9900 } },{ name: "Support Add-on", quantity: 1,unitPriceMoney: { amount: 2900 } },],});// order.pricingAmounts.totalMoney → 13824// Apply a couponawait flint.orders.applyCoupon(order.orderId, {couponCode: "LAUNCH20",});// Pay - amount derived from orderawait flint.orders.pay(order.orderId, {paymentSourceTokens: ["tok_visa"],});// Refund - state auto-transitionsawait flint.refunds.create({paymentIntentId: order.paymentIntentIds[0],amountMoney: { amount: 2900, currency: "USD" },reason: "requested_by_customer",});
Left: you build the orders table, tax integration, and refund reconciliation. Right: the API handles it.
What you get
One integration, not six products
Orders, payments, catalog, billing, invoices, checkout, and real-time events. No separate services to stitch together.
Core
Orders
Create orders with structured line items, quantities, and prices. Totals, tax, and balances are computed automatically on every response.
Payments
Create payment intents from orders. Amount and currency are derived automatically. Stripe handles card processing under the hood.
Refunds
Issue full or partial refunds with one API call. The order balance, tax, and status recalculate automatically. No manual reconciliation.
Commerce
Items & Inventory
Define your product catalog with prices and track inventory. Attach items to orders by reference without duplicating data.
Coupons & Discounts
Create percentage or fixed-amount coupons. Apply to orders and let the discount flow through to computed totals automatically.
Tax
Tax is computed server-side on every order response. Amounts update automatically when line items, coupons, or tips change.
Customers
Store customer profiles with saved payment methods. Attach customers to orders for purchase history and repeat billing.
Billing
Subscription Plans
Define plans with recurring line items and billing intervals. Create once and subscribe many customers.
Subscriptions
Subscribe customers to plans with automatic invoicing and payment collection. Pause, resume, or cancel with one API call.
Distribution
Checkout Sessions
Generate a hosted checkout page from any order without building the form first.
Payment Links
Create shareable payment links that generate orders on click. Good for invoices, one-off charges, and event tickets.
Invoices
Send formal invoices when the buyer pays later or needs internal approval, without pushing billing into a separate system.
Webhooks
Receive real-time notifications for payment, order, and subscription events with signed payloads and automatic retries.
Product Surface
The objects that carry the payment lifecycle
These are the Flint resources that replace the usual hand-built mix of app tables, webhook logic, and disconnected billing tools.
orders
Orders
The primary business record with line items, totals, balances, linked payments, and downstream activity history.
payment_intents
Payments
Processor-backed money movement derived from the order instead of managed as the system of record.
refunds
Refunds
Refund state stays attached to the order workflow instead of becoming an isolated amount you reconcile later.
checkout_sessions
Hosted Checkout
Create an order-backed payment surface for configured purchases, quotes, or balances.
payment_links
Payment Links
Launch reusable hosted flows without abandoning order structure or post-payment context.
invoices
Invoices
Support formal billing and receivables-style follow-up without moving into a disconnected billing system.
subscriptions
Subscriptions
Recurring billing stays close to the same commerce model rather than split into a separate product brain.
webhooks
Events
Receive order-aware event payloads with enough business context to drive support, ops, and automation safely.
Implementation Path
What the order-first integration looks like in practice
This is the cleanest way to think about the system boundary before you get into endpoint-level examples.
Create the order first
Start from line items, customer context, discounts, and totals instead of starting from an amount.
This makes the business record durable before any payment is attempted.
Derive payment collection from that order
Collect money through direct payment, hosted checkout, payment links, or invoices without leaving the same object model.
The collection surface changes. The business record does not.
Mutate the order as the workflow evolves
Apply coupons, refund part of an order, or move into a subscription lifecycle while the net amounts stay computed server-side.
That removes most of the repair logic that normally accumulates around a processor primitive.
Drive support, ops, and automation from one record
Operators and internal tools can read one semantic object instead of reconciling multiple systems.
That is the part most teams only realize they need after launch.
How it works
From order to refund in five API calls
Create an order, apply a coupon, pay, refund a line item, and check the final state. Totals update and statuses transition automatically at every step.
const order = await flint.orders.create({customerId: "cus_01HZ4X8",lineItems: [{name: "Pro Plan - Annual",quantity: 1,unitPriceMoney: { amount: 9900, currency: "USD" },},{name: "Priority Support Add-on",quantity: 1,unitPriceMoney: { amount: 2900, currency: "USD" },},],});// order.status → "OPEN"// order.pricingAmounts.totalMoney → { amount: 13824 }// order.settlementAmounts.outstandingMoney → { amount: 13824 }
const updated = await flint.orders.applyCoupon("ord_01HZ4X9", {couponCode: "LAUNCH20",});// updated.pricingAmounts.discountMoney → { amount: 2560 }// updated.pricingAmounts.taxMoney → { amount: 819 }// updated.pricingAmounts.totalMoney → { amount: 11059 }
const result = await flint.orders.pay("ord_01HZ4X9", {paymentSourceTokens: ["tok_visa"],buyerEmail: "alex@example.com",});// No amount specified.// Card charged via Stripe.// result.order.status → "PAID"
const refund = await flint.refunds.create({paymentIntentId: "pi_01HZ4XA",amountMoney: { amount: 2900, currency: "USD" },reason: "requested_by_customer",idempotencyKey: "refund-support-addon-01",});// order.status → "PARTIALLY_REFUNDED"
const order = await flint.orders.get("ord_01HZ4X9");// order.status → "PARTIALLY_REFUNDED"// order.settlementAmounts.refundedMoney → { amount: 2900 }// order.settlementAmounts.outstandingMoney → { amount: 0 }
Comparison
Flint vs. traditional payment APIs
What you get out of the box with Flint versus what you build yourself on top of a payment-first API.
| Capability | Payment-first | Flint Pay |
|---|---|---|
Order management Line items, quantities, prices | Build from scratch | Built-in order object |
Totals & balances Auto-computed net amounts | Calculate yourself | Computed on every response |
Tax calculation Compute per-item tax | Build or buy separately | Built-in, per line item |
Discounts & coupons Apply, stack, enforce limits | Build from scratch | Built-in with stacking rules |
Refund handling Refund and recalculate | Multi-step across systems | One call, auto-reconciled |
State machine Deterministic lifecycle | Build from scratch | OPEN → PAID → CLOSED |
Subscription billing Plans, trials, retries | Cron jobs + state machine | Auto-billing with lifecycle |
AI agent support Structured data for LLMs | Not possible | Semantic responses + predictable actions |
Why Flint
Built different, on purpose
A payment API should do more than move money. It should understand what you sell and handle the complexity for you.
Order-first, not payment-first
The order is the primitive. Payments, refunds, coupons, and tax attach to it. You never build an orders table or reconcile across systems.
Server-computed totals
Subtotals, tax, discounts, balances, and refunded amounts are computed on every response. You never calculate a total or maintain a ledger.
Automatic state transitions
Pay an order and status moves to PAID. Refund part of it and it moves to PARTIALLY_REFUNDED. No webhook state machine required.
Idempotent by design
Every mutating endpoint accepts an idempotency key. Safe retries, safe webhooks, safe AI agents.
Stripe processes every card
Card data goes directly to Stripe. Same PCI scope, same fraud detection, same dispute handling. Flint adds the commerce layer on top.
AI-ready responses
Responses include line item names, available actions, and deterministic statuses. AI agents can reason about orders without parsing opaque amounts.
What Changes In Your Stack
Flint removes glue code by making the business record first-class
This is the implementation-level difference your team should expect if you adopt an order-first payment model.
You stop building
The shadow commerce layer
You keep
The product workflows you already own
You gain
A cleaner system boundary
Lifecycle
Deterministic order status machine
Every order follows a predictable lifecycle. Transitions are enforced server-side, with no ambiguous states and no manual bookkeeping.
Trust & security
Stripe handles every card
Card data goes to Stripe directly. Flint never sees or stores card numbers. You get the same PCI scope, the same fraud detection, and the same dispute handling you would get with a direct Stripe integration.
Flint adds the commerce layer on top: orders, line items, computed totals, automatic state transitions, coupons, tax, and refund reconciliation. The hard parts that every team ends up building themselves.
{"orderId": "ord_01HZ4X9","status": "PAID","lineItems": [{ "name": "Pro Plan", "quantity": 1, "unitPriceMoney": { "amount": 9900 } }],"pricingAmounts": {"subtotalMoney": { "amount": 9900 },"taxMoney": { "amount": 693 },"totalMoney": { "amount": 10593 }},"settlementAmounts": {"paidMoney": { "amount": 10593 },"outstandingMoney": { "amount": 0 }},"paymentIntentIds": ["pi_01HZ4XA"],"refundIds": [],"activities": [{ "type": "ORDER_CREATED" },{ "type": "PAYMENT_CAPTURED" }]}
Implementation
Go from positioning to proof quickly
This page should convert interest into concrete product verification through the actual API and guide surface.
Operational Surface
The model is easier to operate after launch
These are the practical views internal teams usually need once real customers, refunds, and support tickets show up.
Support
Support tools can start from the order record
The order carries amounts, linked payment intents, refunds, checkout context, and status history, which means support no longer has to correlate three systems to answer a customer question.
Automation
Webhooks and internal jobs operate against semantic state
Event handlers can read business meaning directly from the order payload rather than guessing intent from a processor event plus internal joins.
if (event.type === "order.updated") {const order = event.data;if (order.status === "PARTIALLY_REFUNDED") {notifySupport(order.orderId);updateCustomerLedger(order.customerId, order.settlementAmounts);}}
Internal Tooling
Why better payment structure improves internal software too
The order-first model is not just about checkout. It changes what support, finance, and AI tooling can do safely.
Support
Support agents see one business record
They can answer what was bought, what was refunded, and what still needs action without reconciling several systems.
Ops
Operations workflows get richer event context
Webhook consumers receive payloads that match what the business needs to know, not just whether money moved.
AI
Agent tooling becomes safer
A structured order model gives AI systems deterministic objects and actions instead of ambiguous payment blobs.
Pick The Next Layer
Which page should the reader open next?
This should route buyers into the next highest-signal page based on what they are actually deciding.
The team agrees the payment model itself is the problem
Stripe Alternative
Use the comparison page when the discussion is still charge-first versus order-first.
Commerce API
Use the broader product page when payments, refunds, catalog, and billing all need one platform surface.
Orders API
Drop straight into the docs when the team wants to inspect the object model now.
Fit
Use this API when you need commerce state, not only card collection
This is the dividing line between a payment gateway page and a developer-first payment API page.
Use This When
Choose Something Else When
Vertical SaaS collecting structured purchases
A software platform wants line items, discounts, and post-purchase state in the API so product teams do not keep rebuilding them.
Internal support or agent tooling needs clean semantics
The order object becomes usable by humans and automation because it returns business context directly instead of forcing joins.
Keep Exploring
Related pages for teams shaping the payment model
If this page is the entry point, these are the next pages that explain Flint's broader product surface and the adjacent buying decisions.
const order = await flint.orders.create({customerId: "cus_01HZ4X8",lineItems: [{name: "Pro Plan",quantity: 1,unitPriceMoney: { amount: 9900, currency: "USD" },},],checkoutFlow: "HOSTED",});return order.checkoutSessionUrl;