Hosted Invoices
Commerce automatically generates a secure payment page for every order you create. Send customers the link, and they get a mobile-optimized invoice with embedded checkout—no custom UI needed. We handle OTP verification, payment processing, error recovery, and receipt generation.
What are hosted invoices
When you create an order with /orders/new, Commerce generates two URLs: a web page for payment and a PDF for printing. The web page displays order details—line items, amounts, due dates—and lets customers pay with mobile money through an embedded checkout flow.
The hosted page handles everything: payment method details collection collection, OTP verification, payment confirmation, and receipt download. Your customer never leaves the page, and you never touch sensitive payment data.
Why use hosted invoices
Security and compliance
Hosted invoices are PCI-compliant, TLS-secured, and protected by Content Security Policy headers. Your servers never handle customer payment details, OTP codes, or credentials. This eliminates your PCI compliance burden and reduces security risks to near zero.
Zero maintenance
We manage form validation, OTP collection, error handling, retry logic, payment confirmation, and receipt generation. When mobile money providers update their APIs or add security requirements, we update the hosted pages immediately—no code changes from you.
Better conversion
Optimized through thousands of real transactions: smart payment method defaults, contextual help text, automatic retry on network failures, and progress indicators that reduce drop-offs.
How hosted invoices work
Invoice generation
Every order automatically gets two invoice URLs:
- Web invoice (
invoice.format.web.url) - Mobile-optimized payment page atpages.zebo.dev - PDF invoice (
invoice.format.pdf.url) - Downloadable/printable version
Both are secured with unique identifiers. No authentication required, but each link is single-use and tied to one order.
Payment flow
- Customer opens the web invoice URL
- Sees order details: line items, amounts, due date, beneficiary
- Selects mobile money provider (MTN, Vodafone, AirtelTigo)
- Enters phone number and taps "Pay Now"
- Receives OTP via SMS
- Enters 6-digit code on the page
- We verify with provider and complete payment
- Customer gets instant receipt and confirmation
Timing: 30-45 seconds on good connection. Auto-retry on network drops. OTP resend if expired.
Status tracking
Use /orders/lookup to check payment status. Poll at reasonable intervals (30-60 seconds) or check when the customer returns to your app. The response includes current status, payment timestamps, and balance transaction IDs.
Invoice URLs
Web invoice structure
https://pages.zebo.dev/invoices/{order_id}
The order_id serves as both identifier and security token. Anyone with the URL can view and pay the invoice, but they can't modify amounts or see other orders.
PDF invoice structure
https://pages.zebo.dev/invoices/{order_id}/pdf
Same security model. Download and attach to emails, or let customers print for records.
Delivery methods
The invoice URL works in any sharing context:
Direct redirect
After order creation, return the invoice URL to your client and redirect immediately. Recommended for in-app flows where the customer is already engaged.
Email or SMS
Send the URL through your existing notification system. Invoice URLs are ~70 characters—fits in one SMS with context.
WhatsApp or messaging apps
Share the URL directly. Works in all in-app browsers: WhatsApp, Facebook Messenger, Telegram, or any WebView context.
Common patterns
Subscriptions
Create a new order each billing cycle. Send the hosted invoice URL. Customers pay through the same flow every time. Clean audit trail per transaction.
Deposits and installments
Create separate orders for each payment. Each gets its own invoice URL and receipt. Link via the reference field for tracking.
Multi-currency
Create one order per currency. Hosted invoices display amounts in the order's currency automatically—no conversion logic.
When to use custom checkout
Hosted invoices work for 90% of cases. Build custom checkout only if you need:
- Embedded payment - Form inside your app without redirect
- Pre-order payment - Collect payment before showing details
- Complex conditional logic - Multi-step flows based on user input
- Per-vendor branding - Marketplace where each seller needs unique styling
Otherwise, hosted invoices are simpler, safer, and faster. You can migrate to custom checkout later—the underlying APIs are the same.
Next steps
- Accept payment with hosted invoice — Step-by-step implementation guide
- Orders — Complete order object reference
- Balance transactions — Track funds in your Commerce balance