Skip to main content

Order

Handling Order Webhook Events​

Overview​

When a update for an order is received, our system triggers a webhook event. This event is sent as an HTTP POST request to the endpoint you have specified in the admin dashboard.

Setting Up the Webhook Endpoint​

  • Endpoint Configuration: Define the endpoint in the admin dashboard where webhook events will be sent.
  • Security Measures: Ensure your endpoint is secure and can validate the authenticity of the webhook events received. Each request carries your secret token in the Authorization header — validate it on every request and reject mismatches with 401. The token is sent verbatim (no Bearer prefix) and the body is not signed. See Authorization for the full details, including token rotation.

When you receive it​

The ORDER webhook is sent every time an order changes — it is created, paid, delivered, cancelled, refunded, or its items change. Each call carries the full current state of the order, not just the change. The two moments that matter for the Integration flow:

MomentstatuspaymentStatusExtra fieldsWhat to do
Buyer paidAWAITING_SHIPMENTPAIDpaidAtRelease / ship the goods. The money is held by Sevi; your wallet is not credited yet.
Delivery confirmedDELIVEREDPAIDdeliveredAt, deliveryConfirmedByOrder complete. Your wallet is credited (you also get a TRANSACTION webhook).

deliveryConfirmedBy tells you who confirmed the delivery:

ValueMeaning
SELLERYou, via orderDeliver or the seller dashboard
BUYERThe buyer confirmed receipt in the Sevi app
SEVISevi staff confirmed it (e.g. after a support call)
SYSTEMConfirmed automatically, without a person involved

A DELIVERED webhook for an order you have not called orderDeliver on is normal — the buyer confirmed first. You do not need to call orderDeliver afterwards (doing so is a harmless no-op).

note

paymentStatus: PAID means the buyer paid. You, the seller, are credited when the order is DELIVERED.

Order of delivery​

Webhooks are sent asynchronously and retried on failure, so they can arrive out of order or more than once. Always use the status / paymentStatus in the payload as the current truth, ignore a payload that is "older" than what you already processed (e.g. AWAITING_SHIPMENT after DELIVERED), and use paidAt / deliveredAt for timestamps rather than the time you received the call.

Best Practices​

  • Logging: Keep logs of the webhook events for troubleshooting and auditing purposes.
  • Idempotency: Ensure your webhook handling logic is idempotent to avoid duplicate processing in case of multiple event deliveries.
  • Timely Processing: Process webhook events promptly to maintain up-to-date order status in your system.
  • Return a 200/201 status: The webhook will retry up to 3 times with exponential backoff if a non-200/201 response is returned.

Payload Reference​

The webhook sends a JSON body with two top-level keys: order and customer.

{
"order": { ... },
"customer": { ... }
}

order​

Always present. Contains the order details and related information.

FieldTypeDescription
idstringOrder ID
referenceNumberstring | nullUnique order reference (e.g. ORD-123456)
platformReferencestring | nullExternal platform reference
platformIdstring | nullExternal platform ID
vendorIdstring | nullVendor wallet account
customerIdstring | nullCustomer wallet account
statusstring | nullPENDING, AWAITING_SHIPMENT, DELIVERED, ARCHIVED, CANCELLED, REFUNDED, RETURNED
paymentStatusstringPENDING, PARTIALLY_PAID, CREDIT_PROPOSAL_INITIATED, PAID, PARTIALLY_REFUNDED, REFUNDED
paidAtdatetime | nullWhen the buyer's payment was completed (order became PAID)
deliveredAtdatetime | nullWhen the order was marked DELIVERED. null unless status is DELIVERED
deliveryConfirmedBystring | nullWho confirmed the delivery: SELLER, BUYER, SEVI, SYSTEM. null unless status is DELIVERED
paymentMethodstring | nullSEVI_PAY, SEVI_WALLET, etc.
amountnumberOrder amount
originalAmountnumberOriginal amount before discount
discountnumberDiscount applied
fixedVatnumberFixed VAT amount
percentageVatnumberPercentage VAT
rewardAmountnumberReward amount
currencystring | nullKES, UGX, USD
namestring | nullOrder name / description
phoneNumberstring | nullCustomer phone number on the order
notesstring | nullOrder notes
itemsjson | nullOrder line items (shape varies by platform)
ecommercePlatformstring | nullSEVI, WOOCOMMERCE, etc.
creditConfigurationIdstring | nullCredit configuration used
paymentReferenceNumberstring | nullPayment workflow reference
returnURLstring | nullReturn URL after payment
deliverDirectboolean | nullWhether order is delivered directly
createdByCustomerboolean | nullWhether order was created by the customer
createdAtdatetimeCreation timestamp
approvedByVendordatetime | nullWhen approved by vendor

order.shipping​

Shipping / delivery address. null if not provided.

FieldTypeDescription
idstringShipping address ID
firstNamestring | nullFirst name
lastNamestring | nullLast name
companystring | nullCompany name
address1string | nullAddress line 1
address2string | nullAddress line 2
landmarkstring | nullLandmark
citystring | nullCity
statestring | nullState / province
postcodestring | nullPostal code
countrystring | nullCountry code
emailstring | nullEmail
phoneNumberstring | nullPhone number
longitudestring | nullGPS longitude
latitudestring | nullGPS latitude
shippingTypestring | nullShipping type
shippingFeenumber | nullShipping fee
isDefaultboolean | nullWhether this is the default address
createdAtdatetime | nullCreation timestamp

order.billing​

Billing address. null if not provided.

FieldTypeDescription
idstringBilling address ID
firstNamestring | nullFirst name
lastNamestring | nullLast name
companystring | nullCompany name
address1string | nullAddress line 1
address2string | nullAddress line 2
citystring | nullCity
statestring | nullState / province
postcodestring | nullPostal code
countrystring | nullCountry code
emailstring | nullEmail
phoneNumberstring | nullPhone number

customer​

Customer details as known by the vendor. null if the customer/vendor relationship is not found.

FieldTypeDescription
namestring | nullCustomer name
emailstring | nullCustomer email
referencestring | nullCustomer reference in the vendor's system
phoneNumbersstring[]Customer phone numbers

Full Example​

{
"order": {
"id": "01234567-abcd-...",
"referenceNumber": "ORD-123456",
"platformReference": null,
"platformId": null,
"vendorId": "WAL-vendor-...",
"customerId": "WAL-buyer-...",
"status": "DELIVERED",
"paymentStatus": "PAID",
"paymentMethod": "SEVI_PAY",
"amount": 5000.00,
"originalAmount": 5000.00,
"discount": 0.00,
"fixedVat": 0.00,
"percentageVat": 0.00,
"rewardAmount": 0.00,
"currency": "KES",
"name": "Order for Widget",
"phoneNumber": "+254712345678",
"notes": null,
"items": [
{
"id": "...",
"name": "Widget",
"price": 5000,
"quantity": 1
}
],
"ecommercePlatform": "SEVI",
"creditConfigurationId": "01234567-...",
"paymentReferenceNumber": "wf-...",
"returnURL": null,
"deliverDirect": false,
"createdByCustomer": false,
"createdAt": "2025-01-15T09:00:00.000Z",
"approvedByVendor": "2025-01-15T09:05:00.000Z",
"paidAt": "2025-01-15T09:12:41.000Z",
"deliveredAt": "2025-01-16T14:03:10.000Z",
"deliveryConfirmedBy": "BUYER",
"shipping": {
"id": "01234567-abcd-...",
"firstName": "John",
"lastName": "Doe",
"company": null,
"address1": "123 Main St",
"address2": null,
"landmark": "Near the market",
"city": "Nairobi",
"state": "Nairobi",
"postcode": "00100",
"country": "KE",
"email": "john@example.com",
"phoneNumber": "+254712345678",
"longitude": "36.8219",
"latitude": "-1.2921",
"shippingType": null,
"shippingFee": null,
"isDefault": true,
"createdAt": "2024-08-01T00:00:00.000Z"
},
"billing": {
"id": "01234567-abcd-...",
"firstName": "John",
"lastName": "Doe",
"company": null,
"address1": "123 Main St",
"address2": null,
"city": "Nairobi",
"state": "Nairobi",
"postcode": "00100",
"country": "KE",
"email": "john@example.com",
"phoneNumber": "+254712345678"
}
},
"customer": {
"name": "John Doe",
"email": "john@example.com",
"reference": "CUS018082",
"phoneNumbers": ["+254712345678"]
}
}