General

Invoices

 

Create, update, list and send invoices. Invoices are numbered sequentially, carry a hosted PDF download link and an optional online payment link, and can be sent immediately or scheduled for a future date.

Overview

Invoices bill a customer for one or more products. Every invoice is given a sequential document number on creation, a hosted PDF download link, and an optional online payment link that lets the customer pay the invoice by card.

Invoices are also generated automatically by other parts of the platform:

  • Collections create an invoice per transaction when the collection was submitted with an invoice object.
  • Subscriptions create an invoice per billing cycle.

Automatically generated invoices are linked back to their source through transaction_id and subscription_id. They are read-only apart from their status, and invoices linked to a subscription can not be edited at all.

Invoice status

StatusDescriptionSet by
DRAFTNot yet issued. The invoice is fully editable, has no payment link and is not visible to the customer.You
ISSUEDFinalised and payable. Set this when creating the invoice, when updating a draft, or automatically when the invoice is sent.You
PAIDSettled in full. Set on create to record an invoice that was already paid, set through update to mark an issued invoice as settled, or set automatically when a linked payment succeeds.You / Platform
OVERDUEIssued and still unpaid after the due date.Platform
UNCOLLECTABLEThe linked collection came back unpaid or disputed.Platform
VOIDCancelled after being issued. The document number is retained for audit purposes.Platform

NOTE

Only DRAFT, ISSUED and PAID may be set through the API. OVERDUE, UNCOLLECTABLE and VOID are managed by the platform.

Through update a PAID status may only be applied to an invoice that has already been issued; a draft must be issued first.

Payment collection

payment_collection determines how the invoice gets settled:

ValueDescription
REQUEST_PAYMENTThe customer settles the invoice themselves, using the payment link on the invoice and in the invoice email. This is the default.
AUTOCHARGEThe platform automatically charges the customer's vaulted card on the due date.

WARNING

AUTOCHARGE requires the customer to have a card stored through the card vault API, and the payment method supplied in default_payment_method_id must be the one the card was vaulted against. If the customer has no vaulted card the invoice can not be charged automatically and they will have to pay through the payment link instead, so leave is_payment_link set to true when using AUTOCHARGE.

Totals

Totals are always calculated by the platform from the line items and can not be supplied directly.

Each line is costed and taxed on its own, the way accounting software does it:

  1. The line total excluding VAT is price × qty.
  2. When is_tax is true, 15% VAT is charged on that line total and rounded to the nearest cent. tax is returned on every line item; when is_tax is false it is always 0.00.
  3. The line's total is its total excluding VAT plus its tax.
  4. total_excl is the sum of every line total excluding VAT, total_tax is the sum of every line's tax, and total_incl is the two added together.

Because VAT is rounded per line rather than on the subtotal, an invoice can differ by a cent or two from applying 15% to total_excl directly. Three lines of R10.10 each carry R1.52 of VAT, so the invoice totals R34.86 rather than the R34.85 that taxing the R30.30 subtotal would give. This matches how Xero and Sage total the same document, so invoices reconcile when they are synced across.

NOTE

Quantity is part of the line, not a repeat of it. One line of qty 3 at R10.10 is taxed once on R30.30 (R4.55 of VAT), where three separate lines of qty 1 are taxed three times on R10.10 (R4.56 in total).

total_tax and each line's tax always add up, so an invoice can be reconciled line by line. On an invoice that records a payment already collected, the amount taken is what the invoice must show, so the last line absorbs any rounding difference between it and the sum of the lines. That line's tax can therefore be a cent off 15% of its own total.

Document numbers

document_number is assigned when the invoice record is created (including drafts) and is unique and sequential per account. The format is INV-0000001, or INV-{PREFIX}-0000001 when a custom invoice prefix has been configured on your account. Numbers are never reused, including by deleted invoices.

Create

API call to create new invoices.

Path

POST /invoices/create

Request Body

{
  "records": [{
    "customer_id": "cus_Fjim5EFyD3mUcXWcaoOkP",
    "invoice_status": "DRAFT",
    "items": [{
      "product_id": "pro_MsAXh25ajSIv4s6k52vQn",
      "description": "Good for exercise",
      "price": 45.00,
      "qty": 2
    }],
    "is_tax": true,
    "due_days": 30,
    "payment_collection": "REQUEST_PAYMENT",
    "default_payment_method_id": null,
    "is_payment_link": true,
    "memo": "Thank you for your business.",
    "footer": "Please use the invoice number as your payment reference.",
    "metadata": { "my_key": "my_value" }
  }]
}

Recording an invoice that has already been settled:

{
  "records": [{
    "customer_id": "cus_Fjim5EFyD3mUcXWcaoOkP",
    "invoice_status": "PAID",
    "paid_at": "2026-09-07 14:32:10",
    "items": [{
      "product_id": "pro_MsAXh25ajSIv4s6k52vQn",
      "price": 45.00,
      "qty": 2
    }],
    "is_tax": true
  }]
}

Charging a vaulted card automatically on the due date:

{
  "records": [{
    "customer_id": "cus_Fjim5EFyD3mUcXWcaoOkP",
    "invoice_status": "ISSUED",
    "payment_collection": "AUTOCHARGE",
    "default_payment_method_id": "pam_YxK0zCtJpVpRzdBYTlxnm",
    "items": [{
      "product_id": "pro_MsAXh25ajSIv4s6k52vQn",
      "price": 45.00,
      "qty": 2
    }],
    "is_tax": true,
    "due_days": 30
  }]
}

Response Body

The response follows the same format as the list response

{
  "status": true,
  "records": [{
    "id": "inv_8OPF8BRIXPfaHbXglqVAy",
    "document_number": "INV-0000015",
    ...
  }, ...]
}

Request Parameters

Field
RequiredType
Description
Example
*.customer_idYString(32)Customer to be invoiced, see customers. The customer must have an email address to be able to receive the invoice.cus_Fjim5EFyD3mUcXWcaoOkP
*.invoice_statusNENUMStatus to create the invoice in. Defaults to DRAFT. Use ISSUED to finalise the invoice immediately without sending it, then send it separately. Use PAID to record an invoice that has already been settled, which issues and marks it paid in one call and lets you send the customer a receipt. (DRAFT,ISSUED,PAID)DRAFT
*.paid_atNDatetimeWhen the invoice was paid. Only used with a PAID status and defaults to the current date and time.2026-09-07 14:32:10
*.itemsYArrayLine items being invoiced. At least one item is required.
*.items. *.product_idYString(32)Line item product id, see products API. Any pricing type and billing period may be combined on an invoice.pro_MsAXh25ajSIv4s6k52vQn
*.items. *.descriptionNString(256)Line item description. Defaults to the product description.Good for exercise
*.items. *.priceNDecimalLine item price excluding VAT. Defaults to the product price.45.00
*.items. *.qtyNIntegerLine item quantity, minimum 1. Defaults to 1.2
*.is_taxNBooleantrue - Adds 15% VAT to the invoice total. Defaults to true when your account has a VAT number configured, otherwise false.true
*.due_daysNIntegerNumber of days from the invoice date until payment is due, minimum 1. Defaults to the payment terms configured on your account (30 days).30
*.payment_collectionNENUMHow the invoice will be collected, see payment collection. AUTOCHARGE requires the customer to have a card stored through the card vault. Defaults to REQUEST_PAYMENT. (AUTOCHARGE,REQUEST_PAYMENT)REQUEST_PAYMENT
*.default_payment_method_idCString(32)Payment method used to charge the customer's vaulted card, see payment methods. Required when payment_collection is AUTOCHARGE and must match the payment method the card was vaulted against.pam_YxK0zCtJpVpRzdBYTlxnm
*.is_payment_linkNBooleantrue - Include an online payment link on the invoice and in the invoice email. Defaults to true.true
*.memoNString(2048)Note shown to the customer on the invoice. Defaults to the memo configured on your account.Thank you for your business.
*.footerNString(2048)Footer shown at the bottom of the invoice. Defaults to the footer configured on your account.Please use the invoice number as your payment reference.
*.metadataNObjectCustom key/value data stored against the invoice.{"my_key": "my_value"}

Update

API call to update existing invoices.

What may be updated depends on the current status of the invoice:

  • Draft invoices may be edited or deleted. Every field accepted by create may be changed, the invoice may be issued by setting invoice_status to ISSUED, and it may be deleted by setting invoice_status to DELETED.
  • Issued and overdue invoices may only be marked as paid by setting invoice_status to PAID. No other field may be changed.

Path

POST /invoices/update

Request Body

Only include fields you wish to change (besides id used to find the record).

Editing a draft:

{
  "records": [{
    "id": "inv_8OPF8BRIXPfaHbXglqVAy",
    "due_days": 14,
    "items": [{
      "product_id": "pro_MsAXh25ajSIv4s6k52vQn",
      "price": 45.00,
      "qty": 3
    }]
  }]
}

Deleting a draft:

{
  "records": [{
    "id": "inv_8OPF8BRIXPfaHbXglqVAy",
    "invoice_status": "DELETED"
  }]
}

Marking an issued invoice as paid:

{
  "records": [{
    "id": "inv_8OPF8BRIXPfaHbXglqVAy",
    "invoice_status": "PAID",
    "paid_at": "2026-09-07 14:32:10"
  }]
}

Response Body

The response follows the same format as the list response

{
  "status": true,
  "records": [{
    "id": "inv_8OPF8BRIXPfaHbXglqVAy",
    ...
  }, ...]
}

Request Parameters

Field
RequiredDraft onlyType
Description
Example
*.idY-String(32)Record id to updateinv_8OPF8BRIXPfaHbXglqVAy
*.invoice_statusNNENUMISSUED finalises a draft, DELETED deletes a draft, and PAID marks an issued or overdue invoice as settled. Leave blank to keep the same status. (ISSUED,PAID,DELETED)PAID
*.paid_atNNDatetimeWhen the invoice was paid. Only used with a PAID status and defaults to the current date and time.2026-09-07 14:32:10
*.customer_idNYString(32)Customer to be invoiced, see customers.cus_Fjim5EFyD3mUcXWcaoOkP
*.itemsNYArrayOverwrites all line items stored on the invoice; items can not be changed individually so include every item you wish to keep.
*.items. *.product_idYYString(32)Line item product id, see products API.pro_MsAXh25ajSIv4s6k52vQn
*.items. *.descriptionNYString(256)Line item description.Good for exercise
*.items. *.priceNYDecimalLine item price excluding VAT.45.00
*.items. *.qtyNYIntegerLine item quantity, minimum 1.3
*.is_taxNYBooleantrue - Adds 15% VAT to the invoice total.true
*.due_daysNYIntegerNumber of days from the invoice date until payment is due, minimum 1.14
*.payment_collectionNYENUMSee payment collection. (AUTOCHARGE,REQUEST_PAYMENT)REQUEST_PAYMENT
*.default_payment_method_idCYString(32)Required when payment_collection is AUTOCHARGE and must match the payment method the customer's card was vaulted against.pam_YxK0zCtJpVpRzdBYTlxnm
*.is_payment_linkNYBooleantrue - Include an online payment link on the invoice.true
*.memoNYString(2048)Note shown to the customer on the invoice.Thank you for your business.
*.footerNYString(2048)Footer shown at the bottom of the invoice.Please use the invoice number as your payment reference.
*.metadataNYObjectCustom key/value data stored against the invoice.{"my_key": "my_value"}

WARNING

Invoices linked to a subscription can not be edited at all, only their status may be changed.

Deleting is only possible while the invoice is a draft. An issued invoice must be voided instead so that the document number remains on record, which can be done from the Kwik dashboard.

List

List invoices loaded on the platform, including the PDF download link and the online payment link.

Path

GET /invoices/list

Query Parameters

Field
Type
RequiredDescription
Example
invoice_statusENUMNFilter for a specific invoice status. (DRAFT,ISSUED,PAID,OVERDUE,UNCOLLECTABLE,VOID).ISSUED
invoice_idString(32)NFilter for a specific invoice id.inv_8OPF8BRIXPfaHbXglqVAy
document_numberString(128)NFilter for a specific invoice document number.INV-0000015
customer_idString(32)NFilter for a specific customer id.cus_Fjim5EFyD3mUcXWcaoOkP
subscription_idString(32)NFilter for invoices generated by a specific subscription.sub_kFPzq4kLpuTPgOsZ2sVwB
transaction_idString(32)NFilter for the invoice generated by a specific transaction.tra_VLSEUZK5STgmP4J6yBDlU
payment_collectionENUMNFilter for a specific collection method. (AUTOCHARGE,REQUEST_PAYMENT).REQUEST_PAYMENT
searchString(128)NSearch across the customer name, customer email and document number.Superior Meteor
date_startDate(YYYY-MM-DD)NFilter for invoices created on or after this date.2026-06-14
date_endDate(YYYY-MM-DD)NFilter for invoices created on or before this date.2026-10-26
date_due_startDate(YYYY-MM-DD)NFilter for invoices due on or after this date.2026-07-06
date_due_endDate(YYYY-MM-DD)NFilter for invoices due on or before this date.2026-08-04
date_sent_startDate(YYYY-MM-DD)NFilter for invoices sent on or after this date.2026-07-06
date_sent_endDate(YYYY-MM-DD)NFilter for invoices sent on or before this date.2026-08-04
pageIntegerNPage of results to return, starting at 1. Defaults to 1.2
per_pageIntegerNNumber of invoices per page, minimum 1. Defaults to 100 and is capped at 500.100

Response Body

{
  "status": true,
  "pagination": {
    "total": 215,
    "per_page": 100,
    "current_page": 1,
    "last_page": 3,
    "next_page": 2,
    "prev_page": null
  },
  "records": [{
    "id": "inv_8OPF8BRIXPfaHbXglqVAy",
    "created_at": "2026-09-07 10:30:00",
    "updated_at": null,
    "deleted_at": null,
    "archived_at": null,
    "document_number": "INV-0000015",
    "invoice_status": "ISSUED",
    "customer_id": "cus_Fjim5EFyD3mUcXWcaoOkP",
    "subscription_id": null,
    "transaction_id": null,
    "items": [{
      "product_id": "pro_MsAXh25ajSIv4s6k52vQn",
      "name": "Monthly Membership",
      "description": "Good for exercise",
      "price": 45.00,
      "qty": 2,
      "tax": 13.50,
      "total": 103.50
    }],
    "is_tax": true,
    "total_excl": 90.00,
    "total_tax": 13.50,
    "total_incl": 103.50,
    "due_days": 30,
    "due_date": "2026-10-07",
    "payment_collection": "REQUEST_PAYMENT",
    "default_payment_method_id": null,
    "is_payment_link": true,
    "download_link": "https://invoices.kwik.co.za/download/xDq1ZbW...",
    "payment_link": "https://pay.kwik.co.za/invoice/xDq1ZbW...",
    "email_cc": "accounts@mail.com",
    "date_send_scheduled": null,
    "date_invoice_sent": "2026-09-07 10:31:44",
    "paid_at": null,
    "memo": "Thank you for your business.",
    "footer": "Please use the invoice number as your payment reference.",
    "metadata": { "my_key": "my_value" }
  }, {
    ...
  }]
}

Response Parameters

FieldTypeDescription
Example
statusBooleantrue - success, false - errortrue
paginationObjectPaging detail for the current result set
*.totalIntegerTotal invoices matching the filters215
*.per_pageIntegerInvoices returned per page100
*.current_pageIntegerPage returned1
*.last_pageIntegerLast available page3
*.next_pageIntegerNext page, null on the last page2
*.prev_pageIntegerPrevious page, null on the first pagenull
recordsArray of objects
*.idString(32)Unique ID of the invoiceinv_8OPF8BRIXPfaHbXglqVAy
*.created_atDatetimeDate and time the invoice was created2026-09-07 10:30:00
*.updated_atDatetimeDate and time the invoice was last updated2026-09-08 08:12:05
*.deleted_atDatetimeDate and time the draft invoice was deleted2026-09-09 11:00:00
*.archived_atDatetimeDate and time the invoice was archived2027-04-03 09:15:00
*.document_numberString(128)Sequential invoice number shown to the customerINV-0000015
*.invoice_statusENUM(DRAFT,ISSUED,PAID,OVERDUE,UNCOLLECTABLE,VOID)ISSUED
*.customer_idString(32)Customer being invoiced, see customerscus_Fjim5EFyD3mUcXWcaoOkP
*.subscription_idString(32)Subscription that generated this invoice, null when created directlysub_kFPzq4kLpuTPgOsZ2sVwB
*.transaction_idString(32)Transaction that generated this invoice, null when created directlytra_VLSEUZK5STgmP4J6yBDlU
*.itemsArray of objectsLine items being invoiced
*.items. *.product_idString(32)Line item product id, see products APIpro_MsAXh25ajSIv4s6k52vQn
*.items. *.nameString(128)Line item product name at the time of invoicingMonthly Membership
*.items. *.descriptionString(256)Line item descriptionGood for exercise
*.items. *.priceDecimalLine item price excluding VAT45.00
*.items. *.qtyIntegerLine item quantity2
*.items. *.taxDecimalVAT charged on this line, rounded to the nearest cent. 0.00 when is_tax is false13.50
*.items. *.totalDecimalLine total including VAT, being price × qty plus tax103.50
*.is_taxBooleantrue - 15% VAT was added to the invoice totaltrue
*.total_exclDecimalInvoice total excluding VAT, being the sum of every line total excluding VAT90.00
*.total_taxDecimalTotal VAT on the invoice, being the sum of every line's tax. 0.00 when is_tax is false13.50
*.total_inclDecimalInvoice total including VAT, being total_excl plus total_tax103.50
*.due_daysIntegerNumber of days from the invoice date until payment is due30
*.due_dateDate(YYYY-MM-DD)Date payment is due, calculated as the created date plus the due days2026-10-07
*.payment_collectionENUMSee payment collection. (AUTOCHARGE,REQUEST_PAYMENT)REQUEST_PAYMENT
*.default_payment_method_idString(32)Payment method used to charge the customer's vaulted card when payment_collection is AUTOCHARGE, see payment methodspam_YxK0zCtJpVpRzdBYTlxnm
*.is_payment_linkBooleantrue - The invoice includes an online payment linktrue
*.download_linkStringLink the customer uses to download the invoice PDF. Available on every invoice, including drafts.https://invoices.kwik.co.za/download/xDq1ZbW...
*.payment_linkStringLink the customer uses to pay the invoice online. null while the invoice is a draft, when is_payment_link is false, and once the invoice is paid.https://pay.kwik.co.za/invoice/xDq1ZbW...
*.email_ccString(512)Comma separated addresses copied on the invoice emailaccounts@mail.com
*.date_send_scheduledDate(YYYY-MM-DD)Date the invoice is scheduled to be sent, null when not scheduled2026-09-14
*.date_invoice_sentDatetimeDate and time the invoice was last sent, null until the invoice has been sent2026-09-07 10:31:44
*.paid_atDatetimeDate and time the invoice was paid, null while unpaid2026-09-20 08:45:12
*.memoString(2048)Note shown to the customer on the invoiceThank you for your business.
*.footerString(2048)Footer shown at the bottom of the invoicePlease use the invoice number as your payment reference.
*.metadataObjectInvoice metadata{"my_key": "my_value"}

Send

Email an invoice to your customer. The invoice email contains a link to view and download the invoice, and an online payment link when is_payment_link is true.

Sending a DRAFT invoice issues it, changing the status to ISSUED. Invoices that have already been sent can be sent again as a reminder, and paid invoices can be sent to provide the customer with a receipt.

Path

POST /invoices/send

Request Body

Send immediately to the customer's billing email address:

{
  "records": [{
    "id": "inv_8OPF8BRIXPfaHbXglqVAy"
  }]
}

Send with a copy to additional addresses, scheduled for a future date:

{
  "records": [{
    "id": "inv_8OPF8BRIXPfaHbXglqVAy",
    "cc_email": "accounts@mail.com, auditor@mail.com",
    "schedule": "2026-09-14"
  }]
}

Response Body

The response follows the same format as the list response

{
  "status": true,
  "records": [{
    "id": "inv_8OPF8BRIXPfaHbXglqVAy",
    "invoice_status": "ISSUED",
    "date_send_scheduled": "2026-09-14",
    "date_invoice_sent": null,
    ...
  }, ...]
}

Request Parameters

Field
RequiredType
Description
Example
*.idYString(32)Invoice record ID to sendinv_8OPF8BRIXPfaHbXglqVAy
*.cc_emailNString(512)Comma separated list of addresses to copy on the invoice email.accounts@mail.com, auditor@mail.com
*.scheduleNDate(YYYY-MM-DD)Date on which to send the invoice. Must be a future date. Leave this out to send the invoice immediately.2026-09-14

Recipient

The invoice is always emailed to the linked customer record, so the address can not be set per send. The billing_email on the customer is used when it is set, otherwise the customer's email is used. Update the customer through the customers API to change where invoices are delivered.

When the customer has neither a billing_email nor an email there is nowhere to send the invoice and the request fails with a validation error.

NOTE

A scheduled invoice is issued straight away but only emailed on the scheduled date, so date_invoice_sent stays null until it goes out. Send the invoice again without a schedule to cancel the schedule and email it immediately.