Skip to main content

Integration flow

This page describes the standard way to accept Sevi as a payment provider. Sandbox (https://sandbox.sevi.io/graphql) behaves exactly like production (https://partner.sevi.io/graphql), so whatever you build and test against the sandbox works the same way in production.

The flow in one picture​

Click a step number to jump to its explanation, or a link under it for the API / webhook reference.

Your system (ERP / shop)
Sevi
Buyer
Call orderCreate
Send the invoice: items, buyer phone, your invoice no. in platformReference.
Order created
PENDINGpayment PENDING
orderCreate
id · referenceNumber · paymentLink
Credit / wallet covers it?
YesAuto-deducted from credit, then wallet. No buyer action.
NoBuyer gets the payment link for the rest (2 days to pay).
Auto-deduct requires seller-initiated payment to be enabled.
Pays the rest (only if needed)
Opens the payment link: M-Pesa, wallet or Sevi credit.
paymentLink
Release the goods
The buyer has paid.
Money held by Sevi
AWAITING_SHIPMENTPAID
The seller is not credited yet.
ORDER webhook
ERP marks the order delivered
Call orderDeliver as soon as your ERP marks the delivery done.
Delivery recorded
Whichever confirmation comes first wins.
Confirms receipt
Optional, in the Sevi app.
orderDeliver
or confirms in app
Mark the invoice paid
Book the money as received.
Seller wallet credited
DELIVEREDTOP_UP · COMPLETED
hold.wasHeld = true
ORDER + TRANSACTION webhooks
Money in your bank
Bank account, M-Pesa paybill or till.
Wallet paid out
Automatically, every evening (EAT).
daily payout

Step by step​

1. Create the order​

Call orderCreate with your invoice: items, buyer phone number, billing and shipping details and your own invoice number in platformReference. Store the returned order.id and order.referenceNumber — you need the id for orderDeliver and both appear on every webhook.

Authenticate with the API token of your seller account, see Authentication.

2. Let the buyer pay​

How the payment is collected depends on the buyer's available Sevi credit:

  • Credit available → automatic. If your seller account has seller-initiated payment enabled (ask Sevi to switch it on), Sevi charges the buyer as soon as the order is created, with no buyer action. The amount is taken from the buyer's available Sevi credit first, then from their Sevi wallet balance.
  • Not enough credit → buyer interaction required. Whatever credit and wallet don't cover, the buyer pays through the payment link: Sevi sends them a top-up request, and they have 2 days to pay before the payment is cancelled and any partial funds are refunded. Without seller-initiated payment, the buyer always pays through the link.

orderCreate returns a paymentLink. Redirect the buyer to it, send it by SMS/email, or print it as a QR code on the invoice — see Payment link. On the payment page the buyer chooses M-Pesa, their Sevi wallet, or (if eligible) Sevi credit / pay later.

Either way you receive the same PAID webhook in step 3.

Optionally pass a returnURL so the buyer is sent back to your shop after paying — see Return URL. The return URL is for user experience only; the webhook is the source of truth.

3. Receive the "paid" notification​

When the payment is complete Sevi sends an ORDER webhook with:

  • status: "AWAITING_SHIPMENT"
  • paymentStatus: "PAID"
  • paidAt: when the payment was captured

At this moment the buyer has paid but the money is held by Sevi until the goods are delivered. You can now release the goods.

4. Deliver and confirm delivery​

Ship the goods, then confirm the delivery in one of these ways:

  • Your ERP updates the order in Sevi as delivered by calling orderDeliver with the order id. This is the expected integration: trigger it automatically when your driver/ERP marks the delivery done, so the seller is paid without waiting for the buyer. For a partial delivery pass the delivered amount.
  • The buyer confirms receipt in the Sevi mobile app.

Whichever happens first completes the order; the second one is a harmless no-op. So it is normal to receive a DELIVERED webhook for an order you have not called orderDeliver on yet — check deliveryConfirmedBy to see who confirmed it.

5. Receive the "delivered" and "credited" notifications​

After delivery Sevi sends:

  • an ORDER webhook with status: "DELIVERED", deliveredAt and deliveryConfirmedBy (SELLER, BUYER, SEVI or SYSTEM);
  • a TRANSACTION webhook for the seller wallet: transactionType: "TOP_UP", status: "COMPLETED", paymentType: "ORDER", orderId set and hold.wasHeld: true with hold.releasedAt. This is the moment the money is credited to your Sevi wallet.

The order is now complete. Mark the invoice as paid in your system.

6. Settlement​

The available balance of your Sevi wallet is paid out automatically once a day (in the evening, East Africa Time) to your registered bank account, M-Pesa paybill or till. Each payout arrives on the transaction webhook as a DEDUCT with paymentType: "MONEY_REQUEST" and no orderId; a payout fee, if any, arrives as a separate DEDUCT.

Status reference​

What happenedorder.statusorder.paymentStatusSeller wallet credited?
Order created, buyer has not paidPENDINGPENDINGNo
Buyer paid part (deposit for credit)PENDINGPARTIALLY_PAID / CREDIT_PROPOSAL_INITIATEDNo
Buyer paid in full / credit approvedAWAITING_SHIPMENTPAIDNo — held by Sevi
Delivery confirmedDELIVEREDPAIDYes
Order abandoned before payment, or cancelled with orderCancelARCHIVED / CANCELLEDPENDINGNo
Refunded / returnedREFUNDED / RETURNEDREFUNDED / PARTIALLY_REFUNDEDReversed

Rules of thumb​

  • Use webhooks, not polling. Configure the ORDER and TRANSACTION webhooks (Webhooks). Use orderSearch only to reconcile or to recover after downtime.
  • Webhooks can arrive out of order and can be retried. Always act on the current status / paymentStatus in the payload, and make your handler idempotent (key on order.id / transaction id).
  • PAID ≠ seller paid. The seller wallet is credited only after delivery is confirmed. Use the TRANSACTION webhook (or order.status = DELIVERED) for your "money received" bookkeeping.
  • Do not parse descriptions. Use status, transactionType, orderId and the hold object. Descriptions are human-readable text and may change.
  • Only call orderDeliver after PAID. Earlier calls are rejected (not queued) — retry after the paid webhook.
  • Unpaid orders expire. If the buyer never pays, the order is archived automatically; call orderCancel to close it immediately when the buyer abandons checkout.

Optional: show credit options up front​

Before creating the order you can call orderPaymentProposals with the same input as orderCreate to show the buyer which pay-later options Sevi would offer. This is not required — the payment page shows the same options.