Checkout
Convert the active cart into an order, run payment, and return everything the caller needs to confirm or redirect. The body is **flat**: fields like `cart_id`, `customer`, and `payment_method` sit at the top level. There is no `checkout_data` wrapper.
POST /api/v1/checkout
Process a cart checkout. The server validates the cart, charges the chosen payment method, creates an order, and emits an order created event. On success the response includes a guest bill_token; store it client-side for unauthenticated order lookups.
Body
| Field | Type | Description |
|---|---|---|
cart_id | string | Cart to charge. Required. |
customer | object | { name, email, phone, notes?, save_details }. Email or phone required. |
order_type | string | One of delivery, pickup, dine-in, walk-in (kebab-case). |
address_info | object | Delivery / pickup details. All fields optional. |
payment_method | string | Provider channel, e.g. mobile_money, card, cash. |
mobile_money_details | object | { phone_number, provider, provider_other? } when paying via MoMo. |
special_instructions | string | Note attached to the order. |
idempotency_key | string | Client key to dedupe retries. Same effect as the header. |
pay_currency | string | ISO 4217 code if the customer is paying in a non-cart currency. |
fx_quote_id | string | Pre-locked FX quote from POST /fx/quotes. |
metadata | object | Pass-through, e.g. { success_url, cancel_url }. |
Request
curl -X POST https://api.cimplify.io/api/v1/checkout \
-H "X-Public-Key: pk_test_your_publishable_key" \
-H "Idempotency-Key: 5b1f9d80-2c70-4f2c-bf61-a0e6fa6b02a1" \
-H "Content-Type: application/json" \
-d '{
"cart_id": "cart_01H…",
"customer": {
"name": "Ama Mensah",
"email": "ama@example.com",
"phone": "+233241234567",
"save_details": true
},
"order_type": "delivery",
"address_info": {
"street_address": "12 Independence Ave",
"city": "Accra",
"country": "GH"
},
"payment_method": "mobile_money",
"mobile_money_details": {
"phone_number": "+233241234567",
"provider": "mtn"
},
"metadata": {
"success_url": "https://shop.example.com/orders/success",
"cancel_url": "https://shop.example.com/cart"
}
}'Response
{
"success": true,
"data": {
"order_id": "ord_01H…",
"order_number": "ORD-1284",
"bill_token": "bt_n3k…",
"payment_status": "pending",
"payment_reference": "ref_kjz…",
"redirect_url": "https://pay.example.com/checkout/sess_01H…",
"amount": "13.06",
"currency": "GHS"
}
}Persist bill_token for guests; it’s the proof-of-ownership query parameter on GET /api/v1/orders/:id?token=…. Authenticated customers don’t need it; the server matches the order to their account.
Errors
400 VALIDATION_ERROR: missing customer contact, emptypayment_method, invalid email/phone.404 NOT_FOUND:cart_iddoesn’t exist or doesn’t belong to this session.409 CONFLICT: replay of a previously-completedidempotency_keywith a mismatched body.503 SERVICE_UNAVAILABLE: payment provider rejected or timed out; safe to retry with the same key.
POST /api/v1/payments/authorization
Submit a payment authorization (e.g. 3DS challenge result, MoMo OTP) for an in-flight checkout. The reference comes from the original checkout response.
Request
curl -X POST https://api.cimplify.io/api/v1/payments/authorization \
-H "X-Public-Key: pk_test_your_publishable_key" \
-H "Content-Type: application/json" \
-d '{
"reference": "ref_kjz…",
"auth_type": "otp",
"value": "847362"
}'Response
{
"success": true,
"data": {
"reference": "ref_kjz…",
"status": "approved",
"next_action": null
}
}-
Next: Orders Look up the order, poll payment status, fire cancellations.
-
FX Lock a quote before checkout to honour a specific rate.
Cart
The cart is server-owned and bound to the caller’s session. Items are added by `item_id` with an optional `variant_id` and add-on selections. The same cart is read on the storefront and on checkout; there is no client-side cart sync.
Auth
Customer-facing OTP login. Requesting an OTP delivers a 4–6 digit code over SMS or email; verifying it issues a session cookie that subsequent calls (cart, checkout, orders) recognise as the same customer.