One order buys one listing. Checkout is three calls and Stripe’s payment form; after that, the order moves on by transitions until the buyer has it and the seller is paid. Every call sends the buyer’s session.
1. Quote
Section titled “1. Quote”Show what the buyer will pay before they pay it:
POST /v1/me/orders/quote{ "listing_id": "8f3c…", "currency": "EUR", "delivery": { "method": "shipping", "option": "standard", "address": { "name": "Mia Holm", "line1": "Hallvägen 29", "postal_code": "121 62", "city": "Johanneshov", "country": "SE", "phone": "+46…" } }, "voucher_code": "SPRING10"}{ "currency": "EUR", "total": 61900, "line_items": [ { "code": "item", "label": "Eames lounge chair", "unit_price": 59000, "quantity": 1, "amount": 59000 }, { "code": "shipping", "label": "Shipping", "unit_price": 8800, "quantity": 1, "amount": 8800 }, { "code": "voucher", "label": "Voucher SPRING10", "unit_price": -5900, "quantity": 1, "amount": -5900 } ]}- Show
line_itemsas they come, bylabel, andtotalas the amount to pay. Don’t add things up yourself. - Quote again whenever the delivery, address or voucher changes. Placing the order prices it the same way.
currencyis what the buyer pays in: one of the marketplace’s, the listing’s when left out.
Line item codes:
| Code | Meaning |
|---|---|
item |
The listing. |
shipping |
Delivery, priced. |
collect |
Collected at the showroom or warehouse where it’s stored. Free. |
shipping_address_needed |
Ask for the address; the price comes with it. Placing without one fails. |
shipping_quote |
Delivery can’t be priced here: the marketplace sends a quote after the order. |
voucher |
A discount (negative). |
A voucher that doesn’t apply gives 422 with the reason on body.voucher_code. Show it next to the voucher field.
2. Place the order
Section titled “2. Place the order”POST /v1/me/ordersIdempotency-Key: 6f1d3c5e-…{ the same body as the quote }{ "order": { "id": "1a2b…", "state": "pending_payment", "total": 61900, "currency": "EUR", "available_transitions": [] }, "payment": { "client_secret": "pi_3Q…_secret_…" }}- This reserves the listing and starts the payment. The buyer has 15 minutes to pay; then the order becomes
payment_expiredand the listing is released. - Send an
Idempotency-Key(a new UUID for each press of “Pay”), so a retried request can’t place two orders. 409means it can’t be bought right now: sold, reserved by someone else, or the delivery isn’t possible. Show thedetailand go back to the listing.
3. Take the payment with Stripe
Section titled “3. Take the payment with Stripe”Payments run on the marketplace’s Stripe account. Use Stripe’s Payment Element with the marketplace’s Stripe publishable key (the team gives it to you; it’s public) and the order’s client_secret. Cards, Klarna and the other methods the marketplace has turned on in Stripe appear by themselves.
import { loadStripe } from '@stripe/stripe-js'
const stripe = await loadStripe(STRIPE_PUBLISHABLE_KEY)const elements = stripe.elements({ clientSecret: payment.client_secret })elements.create('payment').mount('#payment')
// On "Pay":const { error } = await stripe.confirmPayment({ elements, confirmParams: { return_url: `${location.origin}/orders/${order.id}` },})if (error) showError(error.message) // otherwise Stripe sends the buyer to return_urlWhen Stripe confirms the payment, mongrl moves the order to purchased. That happens in the background, a moment after the buyer lands on your order page: read the order (GET /v1/me/orders/{id}) and, while it’s still pending_payment, check again every couple of seconds.
In the test environment, pay with Stripe’s test card 4242 4242 4242 4242, any future date and any CVC.
Order states
Section titled “Order states”(new) ─request-payment─▶ pending_payment ─confirm-payment─▶ purchased └─expire-payment (15 min)─▶ payment_expiredpurchased ─mark-delivered─▶ delivered ─mark-received / auto (14 days)─▶ receivedpurchased ─mark-received-early─▶ receivedpurchased ─cancel / auto-cancel (14 days)─▶ canceleddelivered ─dispute─▶ disputed ─resolve-received─▶ received └─resolve-canceled / auto (60 days)─▶ canceledpayment_expired, received and canceled are final. Each order has history: every transition with when it happened, for a timeline on the order page.
Moving an order on
Section titled “Moving an order on”Each order has available_transitions: what this user may do now. Show a button for each and nothing else.
POST /v1/me/orders/{id}/transitions/mark-delivered{ "data": { "tracking_number": "JJSE00012345", "carrier": "PostNord" } }| Transition | Who | When |
|---|---|---|
mark-delivered |
the seller | It’s sent or handed over. data can carry tracking_number and carrier; they appear in order.delivery. |
mark-received |
the buyer | They have it. The seller is paid. |
mark-received-early |
the buyer | They have it before it was marked sent (e.g. picked up). The seller is paid. |
dispute |
the buyer | Something’s wrong after delivery. The marketplace’s team resolves it. |
When the marketplace delivers a listing itself (fulfilment: marketplace, e.g. stored listings), its team marks the order sent in the console. The timers keep orders moving if nobody acts: an order that’s never sent is canceled and refunded after 14 days; a delivered order counts as received after 14 days.
Listing orders
Section titled “Listing orders”GET /v1/me/orderslists the buyer’s purchases;?as=sellerlists their sales. Filter withstate; page withlimitandoffset.- Each order has
line_items,total,deliveryand, for the seller,payout:subtotal,commission,storage_fee,amountand itsstatus(pendinguntil the buyer has it, thenpaid;waiting_for_payout_detailsuntil the seller sets up payouts).
Emails mongrl sends
Section titled “Emails mongrl sends”Buyers and sellers get emails when an order is paid, sent and received, each linking to https://<your shop>/<lang>/orders/<id>. Build that page. See Pages your shop needs.
Checklist
Section titled “Checklist”- Checkout: delivery choice, address, voucher, live quote, “Pay” with the Payment Element.
-
Idempotency-KeyonplaceOrder. - The order page waits for
purchasedafter Stripe returns, then shows the timeline and the buttons fromavailable_transitions. - A delivery-time picker when the order offers one. See Shipping and delivery.