Invoice Lifecycle
Overview
The invoice flow ties together collection, customer management, payment links, and Tanzania Revenue Authority (TRA) fiscal receipts. A merchant creates an invoice, MALIPOPAY generates a shareable payment link, the customer pays via any channel, the merchant receives confirmation, and MALIPOPAY issues the TRA fiscal receipt automatically.
Sequence diagram
sequenceDiagram
autonumber
participant M as Merchant App
participant API as Central API
participant URL as URL Shortener
participant SMS as SMS Service
participant C as Customer
participant GW as Gateway Service
participant TRA as TRA Service
M->>API: POST /invoice<br/>apiToken, customer, items, amount
API->>API: validate, compute totals<br/>+ VAT
API->>URL: create short link<br/>for payment page
URL-->>API: shortCode
API-->>M: 201 { invoiceId, shortUrl }
M->>API: POST /invoice/send<br/>channel: sms | whatsapp
API->>SMS: send notification<br/>with short link
SMS->>C: SMS / WhatsApp with link
C->>API: GET /invoice/{shortCode}<br/>(payment page)
API-->>C: render hosted checkout
C->>API: POST /payment/collection<br/>(from hosted checkout)
API->>GW: route to operator
GW-->>API: payment confirmed
API->>API: mark invoice PAID<br/>generate internal receipt
API->>TRA: POST fiscal receipt request
TRA-->>API: fiscal receipt number + QR
API->>M: webhook { invoiceId, status: PAID, fiscalReceipt }
API->>SMS: send receipt to customer
SMS->>C: receipt SMS / WhatsApp
Key endpoints
| Step | Endpoint | Notes |
|---|---|---|
| 1 | POST /invoice | Create a draft invoice with line items, customer, tax. |
| 6 | POST /invoice/send | Dispatch the payment link to the customer. Channels: sms, whatsapp, email. |
| 8 | GET /invoice/{shortCode} | Hosted checkout page (rendered for the customer, not for the merchant). |
| 10 | POST /payment/collection | Called by the hosted checkout when the customer picks a channel and pays. |
| 14 | POST <merchant webhook> | Final invoice status push with fiscalReceipt attached. |
TRA integration
For merchants registered with TRA, MALIPOPAY automatically requests a fiscal receipt from the TRA service the moment the payment completes. The fiscal receipt arrives as part of the merchant webhook payload and also as a separate endpoint:
GET /invoice/{invoiceId}/tra/receipt
If the TRA service is unreachable (e.g. TRA downtime), the invoice is marked PAID but fiscalReceipt is null. MALIPOPAY automatically retries the TRA request every 15 minutes for up to 24 hours. The merchant can manually retrigger with:
POST /tra/retry/{invoiceId}
States
DRAFT → SENT → PAID → [FISCAL_PENDING →] FISCAL_ISSUED
↓
VOIDED
A DRAFT invoice can be edited; once SENT it's immutable. VOIDED is terminal: a voided invoice can never be paid.
Cancellation
To cancel an invoice before payment:
POST /invoice/mark-voided
{ "invoiceId": "...", "reason": "customer request" }
After payment, refunds must go through the disbursement flow. See Payment Disbursement.