Orders

Every request a buyer submits on your storefront becomes an order — with a per-workspace number (#1, #2, …), a status, a payment status, a quote, and a message thread. Work them at /dashboard/orders.

Two independent state machines live on every order: status (the work) and paymentStatus (the money). A buyer can pay before you start, after you deliver, or never — the two tracks don't gate each other.

The order lifecycle (status)

requested ──► confirmed ──► in_progress ──► delivered ──► completed
    │
    └──► declined

canceled  ◄── from any state that isn't completed/declined/canceled
Status Meaning
requested Just arrived — needs your yes/no
confirmed You accepted; work hasn't started
in_progress You're working on it
delivered Work handed over, awaiting the buyer's OK
completed Done. Terminal
declined You said no at the start. Terminal
canceled Called off mid-flight (your action). Terminal

Only the seller moves status — buyers never drive it. Transitions are validated: an illegal move (e.g. requesteddelivered) returns 409 INVALID_TRANSITION. The buyer is emailed on every status change, with their private order link.

The payment track (paymentStatus)

unpaid ──► payment_claimed ──► payment_confirmed
   └──────────────────────────────────┘
  • unpaid — the starting state.
  • payment_claimed — the buyer tapped "I have transferred" on their order page (manual-transfer flow).
  • payment_confirmed — you confirmed the money arrived (or, with the Payment module, an online payment settled). You can confirm directly from unpaid too — cash in hand, transfer spotted before the buyer clicked. Terminal: confirming an already-confirmed payment is a 409.

The full payment story — bank details, proof upload, online checkout — is on the Payments page.

Quotes

Every order carries quotedPriceIdr — what the buyer owes:

  • Fixed services: the service price.
  • Package services: the chosen package's price.
  • Hourly services: the hourly rate, as a starting point — set the real total once you've scoped the job.
  • A valid discount code is already subtracted at creation.

Adjust the quote any time before the order reaches a terminal state (PATCH /api/v1/orders/:id with {"quotedPriceIdr": …} — or just edit it in the portal). Changing the quote of a completed/declined/ canceled order is a 409.

The message thread

Each order is also a conversation:

  • Buyer replies come from the buyer's order page (/o/<token>).
  • Your replies notify the buyer by email.
  • Internal notes (isInternal: true) are seller-only — never shown to the buyer, never emailed.

The order list sorts by latest activity, so a fresh buyer message bubbles the order to the top.

The buyer's side

The buyer's only credential is an opaque access token, minted at order creation and delivered in every email — their order page is https://serront.com/o/<token>. It shows status, the quote, the thread, and (while payment is pending) your payment instructions. Anyone with the link can see the order, so buyers should treat it like a private link. Repeat buyers can also see all their orders in the client portal.

API

Method + path Does
GET /api/v1/orders List — filters status, paymentStatus, serviceId, free-text q; cursor-paged by latest activity; per-status counts included
GET /api/v1/orders/:id One order + the full thread (incl. internal notes)
PATCH /api/v1/orders/:id Move status and/or set quotedPriceIdr
POST /api/v1/orders/:id/messages Reply ({"body": …}), or internal note ("isInternal": true)
POST /api/v1/orders/:id/confirm-payment unpaid/payment_claimedpayment_confirmed
GET /api/v1/orders/:id/proof The buyer's payment-proof image (binary)
# Everything that needs your attention
curl -H "Authorization: Bearer sk_live_xxx" \
  "https://serront.com/api/v1/orders?status=requested"

# Accept an order
curl -X PATCH https://serront.com/api/v1/orders/ord_01jx… \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"status": "confirmed"}'

# Reply to the buyer
curl -X POST https://serront.com/api/v1/orders/ord_01jx…/messages \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"body": "Confirmed! Starting on Monday.", "authorName": "Adi"}'

Orders are created by buyers on the public surface (POST /api/v1/public/storefront/:slug/order) — there is no seller-side create endpoint in v1. Webhook events fire on creation, replies, status changes, and payment confirmation — see the event catalog.

See also

  • Payments — instructions, proof, claim/confirm, online checkout.
  • Webhooks — react to order events from your own systems.