Infinity Africa

API Reference

Invoices API

Itemized invoices with an auto-generated invoice number and a built-in "Pay Now" link, so a customer can settle by mobile money the moment they receive it.

Endpoints

POST/v1/invoices

Create an itemized invoice. invoice_number is generated for you.

dashboard or API key
GET/v1/invoices

List invoices (merchant_id required as a query param).

dashboard or API key
GET/v1/invoices/{invoice_id}

Get an invoice.

dashboard or API key
PATCH/v1/invoices/{invoice_id}

Edit an invoice — only while DRAFT.

dashboard or API key
POST/v1/invoices/{invoice_id}/send

DRAFT → SENT.

dashboard or API key
POST/v1/invoices/{invoice_id}/payment-link

Generate (or reuse) a Pay Now link for the remaining balance.

dashboard or API key
PATCH/v1/invoices/{invoice_id}/cancel

Cancel an invoice. Idempotent; rejects an already-PAID invoice.

dashboard or API key

Create an invoice

json — POST /v1/invoices
{
  "merchant_id": "5c1f0b2a-3e21-4b9a-9c33-2f6a1d0e8b71",
  "customer_name": "Juma Traders Ltd",
  "customer_phone": "+255712445310",
  "due_date": "2026-09-01",
  "notes": "Payment due within 14 days of receipt",
  "items": [
    { "description": "Wholesale delivery — 50kg bags", "quantity": "4", "unit_price": "70000.00" },
    { "description": "Transport fee", "quantity": "1", "unit_price": "40000.00" }
  ]
}
json — 201 Created
{
  "success": true,
  "data": {
    "id": "e5f6a7b8-...",
    "merchant_id": "5c1f0b2a-3e21-4b9a-9c33-2f6a1d0e8b71",
    "invoice_number": "INV-20260814-9F3A1C2B",
    "customer_name": "Juma Traders Ltd",
    "customer_phone": "+255712445310",
    "customer_email": null,
    "due_date": "2026-09-01",
    "currency": "TZS",
    "subtotal": "320000.00",
    "tax_amount": "0.00",
    "discount_amount": "0.00",
    "total_amount": "320000.00",
    "amount_paid": "0.00",
    "status": "DRAFT",
    "payment_link_id": null,
    "notes": "Payment due within 14 days of receipt",
    "items": [
      { "id": "...", "description": "Wholesale delivery — 50kg bags", "quantity": "4.00", "unit_price": "70000.00", "line_total": "280000.00", "sort_order": 0 },
      { "id": "...", "description": "Transport fee", "quantity": "1.00", "unit_price": "40000.00", "line_total": "40000.00", "sort_order": 1 }
    ],
    "created_at": "2026-08-14T09:00:00Z",
    "updated_at": "2026-08-14T09:00:00Z"
  }
}

Every invoice starts DRAFT. Nothing is sent to the customer, and it can't be paid, until you call .../send.

Getting an invoice paid

Invoices don't have their own checkout page — they reuse the Payment Links product. POST .../payment-link generates an ordinary payment link for the invoice's remaining balance (total_amount - amount_paid) and returns it in the same shape as the Payment Links API. Only a SENT, PARTIALLY_PAID, or OVERDUE invoice can generate one.

json — POST /v1/invoices/{invoice_id}/payment-link
{
  "success": true,
  "data": {
    "id": "a1b2c3d4-...",
    "amount": "320000.00",
    "status": "ACTIVE",
    "public_slug": "PLK-4M18RT",
    "public_url": "https://pay.infinityafrica.net/link/PLK-4M18RT",
    "...": "same PaymentLinkResponse shape"
  }
}
info

Invoice status follows the payment automatically

When that generated link is paid, Infinity Africa credits amount_paid and moves the invoice to PARTIALLY_PAID or PAID on its own — you don't reconcile this by hand. Listen for the invoice.paid webhook to know the moment it happens.

Status lifecycle

StatusMeaning
DRAFTJust created. Editable. Not payable yet.
SENTSent to the customer. Now payable via a generated Pay Now link.
PARTIALLY_PAIDSome, but not all, of total_amount has been collected.
PAIDFully collected. Terminal.
OVERDUEPast due_date and not yet fully paid.
CANCELLEDCancelled by the merchant. Terminal.