Accept payment with Zebo Checkout
Create an order and redirect your customer to the invoice URL. Commerce handles the payment flow, OTP verification, and receipt generation.
Recommended approach. See Zebo Checkout for why this works better than custom checkout.
Step 1: Create an order
Call /orders/new with customer details, line items, and finalize: true. Finalization seals the order and generates its hosted invoice URLs. Store the order ID for status tracking.
Create order
curl https://api.zebo.dev/orders/new \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"request_meta": {
"idempotency_key": "order_inv_001"
},
"customer_data": {
"name": "Gloria Kesewaa",
"email_address": "[email protected]",
"phone_number": "+233544998605"
},
"finalize": true,
"line_items": [
{
"type": "product",
"product": {
"type": "physical",
"name": "Utility Sneakers",
"quantity": 1,
"price": {
"currency": "ghs",
"value": 20000
}
}
}
]
}'
Response
Partial response. See complete Order object.
{
"order": {
"id": "or_XyZ9kL2mQrTfVqYz1wNb",
"number": "INV-2025-001",
"status": "requires_payment",
"invoice": {
"format": {
"web": {
"url": "https://pages.zebo.dev/invoices/or_XyZ9kL2mQrTfVqYz1wNb"
},
"pdf": {
"url": "https://pages.zebo.dev/invoices/or_XyZ9kL2mQrTfVqYz1wNb/pdf"
}
}
}
}
}
Step 2: Direct customer to payment
Choose how to get the customer to the payment page:
Extract response.order.invoice.format.web.url from the response envelope and return it to your client. Check that order.invoice is present before redirecting; it is omitted when the order is still a draft.
// Server: Return URL to client
return {
invoiceURL: response.order.invoice.format.web.url,
}
// Client: Redirect to invoice
const response = await fetch('/api/create-order', { ... })
const { invoiceURL } = await response.json()
window.location.href = invoiceURL
Step 3: Track payment status
Use /orders/lookup to check payment status. Poll periodically or check when the customer returns to your app. When status becomes "paid", funds are in your Commerce balance.
Check status
curl https://api.zebo.dev/orders/lookup \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"order_id": "or_XyZ9kL2mQrTfVqYz1wNb"
}'
Customization
Configure redirect and cancel URLs
{
"checkout_settings": {
"redirect_url": "https://yoursite.com/order/complete",
"cancel_url": "https://yoursite.com/order/cancelled"
}
}
Strongly recommended for a delightful customer experience. When payment completes, customers land on your redirect_url where you can show order confirmation and next steps. When customers abandon checkout without paying, they land on your cancel_url where you can show incomplete order details or offer alternative payment methods.
Set payment due time
{
"payment_due_after": "2026-09-15T23:59:59Z"
}
Use an RFC 3339 timestamp. The value is returned as payment_due_at on the order.
Add line item details
{
"product": {
"name": "Utility Sneakers",
"about": "Size: 42 | Color: Black"
}
}
Appears below product name on invoice.
Update branding
Change logo, business name, and colors in the Commerce dashboard under Settings → Branding. Applies to all new invoices instantly.
See Checkout customization for more options.
Common patterns
Subscriptions: Create new order each cycle, send new invoice URL.
Deposits: Create separate orders for deposit and balance. Link via reference field.
Multi-currency: Create one order per currency.
See Common patterns for implementation details.
Next steps
- Zebo Checkout — Why Zebo Checkout works better than custom checkout
- Orders — Complete order API reference
- Accept a payment — Build custom checkout (advanced)