Understand invoices

A finalized order includes an invoice—a hosted payment page where customers can review what they owe and complete payment. Draft orders omit invoice; set finalize: true during creation or call Finalize an order when the order is ready. This guide explains when to use the hosted invoice URL instead of building a custom checkout.

Prerequisites

What is an invoice?

When you create an order with finalize: true, Commerce includes two invoice URLs in the { "order": ... } response envelope:

{
  "order": {
    "id": "or_48ZW7BGvYUBWc1i6WBkL2jr0iPQP5jUy76mmmHpt",
    "status": "requires_payment",
    "invoice": {
      "format": {
        "pdf": {
          "url": "https://pages.zebo.dev/invoices/or_48ZW7BGvYUBWc1i6WBkL2jr0iPQP5jUy76mmmHpt/pdf"
        },
        "web": {
          "url": "https://pages.zebo.dev/invoices/or_48ZW7BGvYUBWc1i6WBkL2jr0iPQP5jUy76mmmHpt"
        }
      }
    }
  }
}

The web URL is an interactive payment page. Send this to a customer to let them pay directly. The PDF URL generates a downloadable invoice document—useful for B2B customers who need a paper trail, accounting teams, or email attachments.

The URLs don't require an API key. Treat them as bearer capabilities and share them only with the intended customer.

Web invoice: the hosted payment page

When a customer opens the web invoice URL, they see:

  • Your merchant name and branding
  • A line-by-line breakdown of what they're being charged
  • The total amount and currency
  • A payment form appropriate to their region (mobile money, card, etc.)

Commerce handles the entire payment flow on this page: collecting payment details, sending the OTP, waiting for confirmation, and showing a success or failure state. You don't write any frontend payment code.

This is the approach documented in Accept payment with Zebo Checkout—create the order via API, then redirect or link the customer to the web invoice URL.

PDF invoice: the downloadable document

The PDF URL generates a formatted invoice document on demand—every request to it produces the current state of the invoice. This means:

  • Before payment: the PDF shows an outstanding balance with payment instructions
  • After payment: the PDF shows payment confirmation. Provide receipt_number on Create an order or Update an order when your accounting system needs a receipt reference in order API responses for reconciliation.

PDF invoices are useful when your customers are businesses that need documents for accounting, when you want to email an invoice attachment before requesting payment, or when you're integrating with an ERP that ingests invoice PDFs.

Invoice vs. custom checkout

The hosted invoice (Zebo Checkout) handles the payment experience for you. You create the order, redirect the customer, and poll for completion—or listen for the order.completed webhook. No frontend payment code required.

Building a custom checkout means you manage the UI yourself and call payment endpoints directly: /orders/pay, /orders/confirm_payment, and /orders/request_confirmation. This gives you complete control over the look and feel but requires you to implement the full payment flow, OTP collection UI, and error handling.

Choose Zebo Checkout (hosted invoice) when:

  • Speed to market matters more than exact UI control
  • You want Commerce to handle mobile money OTP flows
  • You're building a simple storefront or order management workflow
  • You don't have frontend engineers to build a custom checkout

Choose custom checkout when:

  • Your brand guidelines require a fully native experience
  • You're embedding payment into an existing mobile app or complex UI
  • You need fine-grained control over payment method selection and UX
  • You've already built a payment UI and want to wire it to Commerce APIs

How the order and invoice stay in sync

The invoice reflects the live order state. If you update an order via /orders/update and reseal it, or seal it with /orders/finalize, the invoice immediately shows the updated total—the customer always sees current numbers, not a stale snapshot.

When payment completes, the invoice transitions from "pay now" to "payment confirmed" automatically. The same URL that showed the payment form now shows a receipt. You don't need to do anything—Commerce handles the state machine.

Was this page helpful?