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 at pages.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

  1. Customer opens the web invoice URL
  2. Sees order details: line items, amounts, due date, beneficiary
  3. Selects mobile money provider (MTN, Vodafone, AirtelTigo)
  4. Enters phone number and taps "Pay Now"
  5. Receives OTP via SMS
  6. Enters 6-digit code on the page
  7. We verify with provider and complete payment
  8. 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

Was this page helpful?