API Reference
Build integrations with the InvoiceFlow REST API. All requests are made over HTTPS and must include a valid API key. API access requires the Business plan.
Base URL
https://www.invoiceflow.techieszon.com/api/v1
Auth
Bearer token
Format
JSON · REST
Overview
All endpoints are relative to the base URL:
https://www.invoiceflow.techieszon.com/api/v1
All responses are JSON. List endpoints return a data array and a meta pagination object:
{
"data": [ ... ],
"meta": { "total": 42, "page": 1, "pageSize": 20, "totalPages": 3 }
}Authentication
Generate API keys in Settings → API Keys. Pass your key on every request:
# Option 1 — Authorization header (recommended) Authorization: Bearer if_live_your_key_here # Option 2 — X-API-Key header X-API-Key: if_live_your_key_here
curl example:
curl -H "Authorization: Bearer if_live_your_key_here" \
https://www.invoiceflow.techieszon.com/api/v1/invoicesJavaScript / TypeScript:
const res = await fetch("https://www.invoiceflow.techieszon.com/api/v1/invoices", {
headers: { Authorization: "Bearer if_live_your_key_here" },
});
const { data, meta } = await res.json();Errors
All errors return a standard JSON body with an error message and a machine-readable code:
{ "error": "Not found", "code": "NOT_FOUND" }Status
Code
Meaning
UNAUTHORIZEDMissing or invalid API keyUPGRADE_REQUIREDBusiness plan requiredNOT_FOUNDResource does not existVALIDATION_ERRORInvalid request bodyRATE_LIMITEDToo many requestsSERVER_ERRORUnexpected server errorRate Limits
100 requests per minute per API key. Limit status is returned in every response:
X-RateLimit-Limit: 100 X-RateLimit-Remaining: 87 X-RateLimit-Reset: 1717000060000
When exceeded, the API returns 429 RATE_LIMITED. Wait until the reset timestamp before retrying.
Invoices
draft · recorded · sent · viewed · partial · paid · overdue · cancelled.recorded invoices are finalized for internal tracking but not sent to the client — they can still be edited and receive payments. Once an invoice moves past draft or recorded it can no longer be edited — only cancelled.taxRate will be "0.00" and the full breakdown is in invoiceTaxLines — an array of { name, type, value, amount } objects. When a flat tax rate is used, taxRate holds the percentage and invoiceTaxLines will be an empty array./api/v1/invoicesList all invoices for your organisation
Parameters
pageintegerPage number (default: 1)page_sizeintegerResults per page, max 100 (default: 20)statusstringFilter: draft · recorded · sent · viewed · partial · paid · overdue · cancelledsearchstringSearch by invoice number{
"data": [
{
"id": "uuid",
"invoiceNumber": "INV-001",
"status": "sent",
"currency": "GHS",
"subtotal": "1500.00",
"total": "1500.00",
"amountPaid": "0.00",
"balanceDue": "1500.00",
"issueDate": "2026-05-01T00:00:00Z",
"dueDate": "2026-05-15T00:00:00Z",
"clientId": "uuid",
"createdAt": "2026-05-01T09:00:00Z"
}
],
"meta": { "total": 42, "page": 1, "pageSize": 20, "totalPages": 3 }
}/api/v1/invoices/:idGet a single invoice with items, client, payments, and tax breakdown
{
"data": {
"id": "uuid",
"invoiceNumber": "INV-001",
"status": "paid",
"currency": "GHS",
"subtotal": "1500.00",
"discountType": null,
"discountValue": "0.00",
"taxRate": "0.00",
"taxAmount": "225.00",
"invoiceTaxLines": [
{ "name": "VAT", "type": "percentage", "value": 15, "amount": 225 }
],
"total": "1725.00",
"amountPaid": "1725.00",
"balanceDue": "0.00",
"issueDate": "2026-05-01T00:00:00Z",
"dueDate": "2026-05-15T00:00:00Z",
"items": [
{ "description": "Web design", "quantity": "1", "unit": "hrs", "rate": "1500.00", "amount": "1500.00" }
],
"client": { "id": "uuid", "name": "Acme Corp", "email": "billing@acme.com" },
"payments": [
{ "amount": "1725.00", "paymentMethod": "bank_transfer", "paymentDate": "2026-05-10T00:00:00Z" }
]
}
}/api/v1/invoicesCreate a new draft invoice
Parameters
itemsarrayrequiredLine items: description, quantity, rate, unit (optional)issueDateISO 8601requiredInvoice issue dateclientIduuidID of the client to billcurrencystring3-letter currency code (default: GHS)dueDateISO 8601Payment due datetaxRatenumberTax percentage 0–100 (default: 0)notesstringNotes shown on the invoicetermsstringTerms & conditions text{
"data": { "id": "uuid", "invoiceNumber": "INV-043", "status": "draft", "total": "1500.00" }
}Clients
/api/v1/clientsList all clients
Parameters
pageintegerPage number (default: 1)page_sizeintegerResults per page, max 100 (default: 20)searchstringSearch by name or email{
"data": [
{ "id": "uuid", "name": "Acme Corp", "email": "billing@acme.com", "country": "GH", "createdAt": "2026-01-01T00:00:00Z" }
],
"meta": { "total": 15, "page": 1, "pageSize": 20, "totalPages": 1 }
}/api/v1/clients/:idGet a client with their recent invoices
{
"data": {
"id": "uuid",
"name": "Acme Corp",
"email": "billing@acme.com",
"recentInvoices": [
{ "id": "uuid", "invoiceNumber": "INV-001", "status": "paid", "total": "1500.00" }
]
}
}/api/v1/clientsCreate a new client
Parameters
namestringrequiredClient display nameemailemailBilling email addresscompanystringCompany or business namephonestringPhone numbercountrystringISO 3166-1 alpha-2 country codecurrencystringDefault billing currency for this client{ "data": { "id": "uuid", "name": "Acme Corp", "createdAt": "2026-05-30T00:00:00Z" } }Receipts
issued · partial · paid_in_full. Receipts are auto-generated when a payment is recorded against an invoice./api/v1/receiptsList all payment receipts
Parameters
pageintegerPage number (default: 1)page_sizeintegerResults per page, max 100 (default: 20){
"data": [
{
"id": "uuid",
"receiptNumber": "RCP-001",
"status": "paid_in_full",
"currency": "GHS",
"amountReceived": "1500.00",
"balanceRemaining": "0.00",
"issueDate": "2026-05-10T00:00:00Z",
"clientId": "uuid",
"invoiceId": "uuid",
"createdAt": "2026-05-10T09:00:00Z"
}
],
"meta": { "total": 8, "page": 1, "pageSize": 20, "totalPages": 1 }
}/api/v1/receipts/:idGet a single receipt with client and payment details
{
"data": {
"id": "uuid",
"receiptNumber": "RCP-001",
"amountReceived": "1500.00",
"client": { "id": "uuid", "name": "Acme Corp" },
"payments": [{ "amount": "1500.00", "paymentMethod": "bank_transfer" }]
}
}Payments
/api/v1/paymentsList all payments across all invoices
Parameters
pageintegerPage number (default: 1)page_sizeintegerResults per page, max 100 (default: 20){
"data": [
{
"id": "uuid",
"invoiceId": "uuid",
"amount": "1500.00",
"currency": "GHS",
"paymentMethod": "mobile_money",
"paymentDate": "2026-05-10T00:00:00Z"
}
],
"meta": { "total": 24, "page": 1, "pageSize": 20, "totalPages": 2 }
}Webhooks
InvoiceFlow delivers HTTP POST requests to your configured endpoint URL when specific events occur. Set up endpoints in Settings → Webhooks.
Events
invoice.createdA new invoice was createdinvoice.sentInvoice was emailed to the clientinvoice.viewedClient opened the public invoice linkinvoice.paidInvoice is fully paidinvoice.overdueInvoice has passed its due date unpaidinvoice.cancelledInvoice was cancelled by the ownerpayment.recordedA payment was recorded on an invoiceclient.createdA new client was createdEach request includes X-InvoiceFlow-Signature and X-InvoiceFlow-Event headers. Verify the signature with your webhook secret (shown once when the endpoint is created):
import { createHmac } from "crypto";
function verifyWebhook(rawBody: string, signature: string, secret: string): boolean {
const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
return signature === expected;
}
// Express example
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
const sig = req.headers["x-invoiceflow-signature"] as string;
if (!verifyWebhook(req.body.toString(), sig, process.env.WEBHOOK_SECRET!)) {
return res.status(401).json({ error: "Invalid signature" });
}
const { event, data } = JSON.parse(req.body.toString());
switch (event) {
case "invoice.paid":
// Mark order as fulfilled, send thank-you email, etc.
break;
case "payment.recorded":
// Sync to your accounting system
break;
}
res.status(200).json({ received: true });
});2xx within 10 seconds.