Skip to content

Invoices API

Create and manage invoices programmatically. Invoices include automatic payment link generation for easy collection.

Generate professional invoices with automatic payment link and QR code generation. Track payment status, manage due dates, apply discounts, and handle partial payments. Each invoice creates a unique payment link that customers can use to pay online.

Use Cases

  • Freelancers & Agencies: Bill clients for projects and services
  • B2B Transactions: Create invoices for business customers
  • Recurring Billing: Generate invoices for subscription-based services
  • E-commerce: Invoice for custom orders or wholesale purchases

Available Endpoints

MethodEndpointDescription
POST/business/invoice/createCreate an invoice
GET/business/invoice/listList all invoices
GET/business/invoice/details/:idGet invoice details
PATCH/business/invoice/update/:idUpdate an invoice

Invoice Statuses

StatusDescription
draftInvoice is being drafted
unpaidInvoice sent, awaiting payment
partially_paidPartial payment received
paidInvoice fully paid
overduePast due date, unpaid
cancelledInvoice cancelled

Create Invoice

Create a new invoice for a customer with automatic payment link generation.

Endpoint

http
POST /business/invoice/create

Request Body

FieldTypeRequiredDescription
customeridstringYesCustomer ID (must exist in your business)
itemsarrayYesInvoice line items (min: 1)
duedatestringYesPayment due date (ISO 8601)
titlestringNoInvoice title (auto-generated if not provided)
descriptionstringNoInvoice description or notes
invoicedatestringNoInvoice date (defaults to current date)
taxidstringNoTax configuration ID
discountnumberNoDiscount amount
discounttypestringNoDiscount type: percentage or fixed
remarkstringNoInternal notes

Item Object

FieldTypeRequiredDescription
itemidstringYesProduct/Service ID
namestringNoItem name
quantityintegerYesQuantity
ratenumberYesPrice per unit

Example Request

bash
curl -X POST "https://api.cashfin.africa/business/invoice/create" \
  -H "Authorization: cs_your_client_secret" \
  -H "Content-Type: application/json" \
  -d '{
    "customerid": "507f1f77bcf86cd799439011",
    "items": [
      {
        "itemid": "507f191e810c19729de860ea",
        "name": "Website Development",
        "quantity": 1,
        "rate": 150000.00
      },
      {
        "itemid": "507f191e810c19729de860eb",
        "name": "Hosting (Annual)",
        "quantity": 1,
        "rate": 12000.00
      }
    ],
    "title": "Website Development Project",
    "description": "Complete website redesign with hosting",
    "duedate": "2024-02-15",
    "discount": 10,
    "discounttype": "percentage"
  }'
javascript
const invoiceData = {
  customerid: "507f1f77bcf86cd799439011",
  items: [
    {
      itemid: "507f191e810c19729de860ea",
      name: "Website Development",
      quantity: 1,
      rate: 150000.0,
    },
    {
      itemid: "507f191e810c19729de860eb",
      name: "Hosting (Annual)",
      quantity: 1,
      rate: 12000.0,
    },
  ],
  title: "Website Development Project",
  description: "Complete website redesign with hosting",
  duedate: "2024-02-15",
  discount: 10,
  discounttype: "percentage",
};

const response = await fetch(
  "https://api.cashfin.africa/business/invoice/create",
  {
    method: "POST",
    headers: {
      Authorization: "cs_your_client_secret",
      "Content-Type": "application/json",
    },
    body: JSON.stringify(invoiceData),
  }
);

const data = await response.json();
console.log(data);
php
<?php
$invoiceData = [
  'customerid' => '507f1f77bcf86cd799439011',
  'items' => [
    [
      'itemid' => '507f191e810c19729de860ea',
      'name' => 'Website Development',
      'quantity' => 1,
      'rate' => 150000.00
    ],
    [
      'itemid' => '507f191e810c19729de860eb',
      'name' => 'Hosting (Annual)',
      'quantity' => 1,
      'rate' => 12000.00
    ]
  ],
  'title' => 'Website Development Project',
  'description' => 'Complete website redesign with hosting',
  'duedate' => '2024-02-15',
  'discount' => 10,
  'discounttype' => 'percentage'
];

$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://api.cashfin.africa/business/invoice/create",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => json_encode($invoiceData),
  CURLOPT_HTTPHEADER => [
    "Authorization: cs_your_client_secret",
    "Content-Type: application/json"
  ],
]);

$response = curl_exec($curl);
$result = json_decode($response, true);

print_r($result);
python
import requests

invoice_data = {
    'customerid': '507f1f77bcf86cd799439011',
    'items': [
        {
            'itemid': '507f191e810c19729de860ea',
            'name': 'Website Development',
            'quantity': 1,
            'rate': 150000.00
        },
        {
            'itemid': '507f191e810c19729de860eb',
            'name': 'Hosting (Annual)',
            'quantity': 1,
            'rate': 12000.00
        }
    ],
    'title': 'Website Development Project',
    'description': 'Complete website redesign with hosting',
    'duedate': '2024-02-15',
    'discount': 10,
    'discounttype': 'percentage'
}

response = requests.post(
    'https://api.cashfin.africa/business/invoice/create',
    headers={
        'Authorization': 'cs_your_client_secret',
        'Content-Type': 'application/json'
    },
    json=invoice_data
)

result = response.json()
print(result)

Success Response

json
{
  "success": true,
  "message": "Invoice created successfully",
  "data": {
    "_id": "507f1f77bcf86cd799439020",
    "invoiceno": "INV-2024-001",
    "title": "Website Development Project",
    "status": "unpaid",
    "balance": 145800.00,
    "invoicedate": "2024-01-15T00:00:00Z",
    "duedate": "2024-02-15T00:00:00Z",
    "items": [
      {
        "itemid": "507f191e810c19729de860ea",
        "name": "Website Development",
        "quantity": 1,
        "rate": 150000.00
      },
      {
        "itemid": "507f191e810c19729de860eb",
        "name": "Hosting (Annual)",
        "quantity": 1,
        "rate": 12000.00
      }
    ],
    "customer": {
      "_id": "507f1f77bcf86cd799439011",
      "name": "John Doe",
      "email": "[email protected]",
      "phone": "+254712345678"
    },
    "paymentlink": {
      "_id": "507f1f77bcf86cd799439021",
      "shorturl": "https://yourbusiness.cashfin.africa/pay/abc12345"
    },
    "qrcode": "https://res.cloudinary.com/cashfin/image/upload/invoice-qr.png",
    "createdat": "2024-01-15T10:30:00Z"
  }
}

Response Fields

FieldDescription
_idUnique invoice identifier
invoicenoHuman-readable invoice number (e.g., INV-2024-001)
titleInvoice title
statusCurrent invoice status
balanceAmount due after discounts
paymentlinkAuto-generated payment collection link
qrcodeQR code URL for quick payments

List Invoices

Retrieve a paginated list of all invoices.

Endpoint

http
GET /business/invoice/list

Query Parameters

ParameterTypeDefaultDescription
pageinteger1Page number
limitinteger10Items per page (max: 100)
statusstring-Filter by status
searchstring-Search in title, description, invoice number
customeridstring-Filter by customer ID

Example Request

bash
curl -X GET "https://api.cashfin.africa/business/invoice/list?page=1&limit=20&status=unpaid" \
  -H "Authorization: cs_your_client_secret"
javascript
const params = new URLSearchParams({
  page: "1",
  limit: "20",
  status: "unpaid",
});

const response = await fetch(
  `https://api.cashfin.africa/business/invoice/list?${params}`,
  {
    headers: {
      Authorization: "cs_your_client_secret",
    },
  }
);

const data = await response.json();
console.log(data);
php
<?php
$params = http_build_query([
  'page' => 1,
  'limit' => 20,
  'status' => 'unpaid'
]);

$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://api.cashfin.africa/business/invoice/list?{$params}",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    "Authorization: cs_your_client_secret"
  ],
]);

$response = curl_exec($curl);
$data = json_decode($response, true);

print_r($data);
python
import requests

response = requests.get(
    'https://api.cashfin.africa/business/invoice/list',
    headers={'Authorization': 'cs_your_client_secret'},
    params={
        'page': 1,
        'limit': 20,
        'status': 'unpaid'
    }
)

data = response.json()
print(data)

Example Response

json
{
  "success": true,
  "data": [
    {
      "_id": "507f1f77bcf86cd799439020",
      "invoiceno": "INV-2024-001",
      "title": "Website Development Project",
      "status": "unpaid",
      "balance": 145800.00,
      "duedate": "2024-02-15T00:00:00Z",
      "createdat": "2024-01-15T10:30:00Z"
    },
    {
      "_id": "507f1f77bcf86cd799439021",
      "invoiceno": "INV-2024-002",
      "title": "Monthly Retainer",
      "status": "paid",
      "balance": 0,
      "duedate": "2024-01-31T00:00:00Z",
      "createdat": "2024-01-10T08:00:00Z"
    }
  ],
  "pagination": {
    "total": 45,
    "page": 1,
    "limit": 20,
    "pages": 3
  }
}

Get Invoice Details

Retrieve detailed information about a specific invoice including customer and payment information.

Endpoint

http
GET /business/invoice/details/:id

Path Parameters

ParameterTypeRequiredDescription
idstringYesInvoice ID (MongoDB ObjectID)

Example Request

bash
curl -X GET "https://api.cashfin.africa/business/invoice/details/507f1f77bcf86cd799439020" \
  -H "Authorization: cs_your_client_secret"
javascript
const invoiceId = "507f1f77bcf86cd799439020";

const response = await fetch(
  `https://api.cashfin.africa/business/invoice/details/${invoiceId}`,
  {
    headers: {
      Authorization: "cs_your_client_secret",
    },
  }
);

const data = await response.json();
console.log(data);
php
<?php
$invoiceId = '507f1f77bcf86cd799439020';

$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://api.cashfin.africa/business/invoice/details/{$invoiceId}",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    "Authorization: cs_your_client_secret"
  ],
]);

$response = curl_exec($curl);
$data = json_decode($response, true);

print_r($data);
python
import requests

invoice_id = '507f1f77bcf86cd799439020'

response = requests.get(
    f'https://api.cashfin.africa/business/invoice/details/{invoice_id}',
    headers={'Authorization': 'cs_your_client_secret'}
)

data = response.json()
print(data)

Example Response

json
{
  "success": true,
  "data": {
    "_id": "507f1f77bcf86cd799439020",
    "invoiceno": "INV-2024-001",
    "title": "Website Development Project",
    "description": "Complete website redesign with hosting",
    "status": "unpaid",
    "balance": 145800.00,
    "subtotal": 162000.00,
    "taxamount": 0,
    "discount": 16200.00,
    "discounttype": "percentage",
    "invoicedate": "2024-01-15T00:00:00Z",
    "duedate": "2024-02-15T00:00:00Z",
    "qrcode": "https://res.cloudinary.com/cashfin/image/upload/invoice-qr.png",
    "items": [
      {
        "itemid": "507f191e810c19729de860ea",
        "name": "Website Development",
        "quantity": 1,
        "rate": 150000.00,
        "total": 150000.00
      },
      {
        "itemid": "507f191e810c19729de860eb",
        "name": "Hosting (Annual)",
        "quantity": 1,
        "rate": 12000.00,
        "total": 12000.00
      }
    ],
    "customer": {
      "_id": "507f1f77bcf86cd799439011",
      "name": "John Doe",
      "email": "[email protected]",
      "phone": "+254712345678"
    },
    "paymentlinks": [
      {
        "_id": "507f1f77bcf86cd799439021",
        "shorturl": "abc12345",
        "rawurl": "https://yourbusiness.cashfin.africa/pay/abc12345",
        "status": "unpaid"
      }
    ],
    "createdat": "2024-01-15T10:30:00Z",
    "updatedat": "2024-01-15T10:30:00Z"
  }
}

Update Invoice

Update an existing invoice. Only certain fields can be updated after creation.

Endpoint

http
PATCH /business/invoice/update/:id

Path Parameters

ParameterTypeRequiredDescription
idstringYesInvoice ID (MongoDB ObjectID)

Request Body

All fields are optional. Only provided fields will be updated.

FieldTypeDescription
titlestringInvoice title
descriptionstringInvoice description
statusstringInvoice status (see valid values below)
duedatestringDue date (ISO 8601 format)
discountnumberDiscount amount
discounttypestringDiscount type: percentage or fixed

Valid Status Values

  • draft
  • unpaid
  • partially_paid
  • paid
  • overdue
  • cancelled

Example Request

bash
curl -X PATCH "https://api.cashfin.africa/business/invoice/update/507f1f77bcf86cd799439020" \
  -H "Authorization: cs_your_client_secret" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "paid",
    "description": "Paid in full on 2024-01-20"
  }'
javascript
const invoiceId = "507f1f77bcf86cd799439020";

const response = await fetch(
  `https://api.cashfin.africa/business/invoice/update/${invoiceId}`,
  {
    method: "PATCH",
    headers: {
      Authorization: "cs_your_client_secret",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      status: "paid",
      description: "Paid in full on 2024-01-20",
    }),
  }
);

const data = await response.json();
console.log(data);
php
<?php
$invoiceId = '507f1f77bcf86cd799439020';

$updateData = [
  'status' => 'paid',
  'description' => 'Paid in full on 2024-01-20'
];

$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://api.cashfin.africa/business/invoice/update/{$invoiceId}",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => "PATCH",
  CURLOPT_POSTFIELDS => json_encode($updateData),
  CURLOPT_HTTPHEADER => [
    "Authorization: cs_your_client_secret",
    "Content-Type: application/json"
  ],
]);

$response = curl_exec($curl);
$result = json_decode($response, true);

print_r($result);
python
import requests

invoice_id = '507f1f77bcf86cd799439020'

response = requests.patch(
    f'https://api.cashfin.africa/business/invoice/update/{invoice_id}',
    headers={
        'Authorization': 'cs_your_client_secret',
        'Content-Type': 'application/json'
    },
    json={
        'status': 'paid',
        'description': 'Paid in full on 2024-01-20'
    }
)

result = response.json()
print(result)

Example Response

json
{
  "success": true,
  "message": "Invoice updated successfully",
  "data": {
    "_id": "507f1f77bcf86cd799439020",
    "invoiceno": "INV-2024-001",
    "updated": {
      "status": "paid",
      "description": "Paid in full on 2024-01-20",
      "updatedat": "2024-01-20T14:30:00Z"
    }
  }
}

Error Responses

Validation Error

json
{
  "success": false,
  "error": "At least one item is required"
}

Customer Not Found

json
{
  "success": false,
  "error": "Customer not found in this business"
}

Product Not Found

json
{
  "success": false,
  "error": "product not found: 507f191e810c19729de860ea"
}

Invoice Not Found

json
{
  "success": false,
  "error": "Invoice not found"
}

Invalid Date Format

json
{
  "success": false,
  "error": "Invalid duedate format. Use ISO 8601 format (YYYY-MM-DD or YYYY-MM-DDTHH:MM:SSZ)"
}

Integration Examples

Complete Invoice Workflow

javascript
import Cashfin from "@cashfin/node";

const cashfin = new Cashfin({ apiKey: process.env.CASHFIN_API_KEY });

async function createAndSendInvoice(customerId, items, dueDate) {
  // 1. Create the invoice
  const invoice = await cashfin.invoices.create({
    customerid: customerId,
    items: items,
    duedate: dueDate.toISOString(),
  });

  console.log(`Invoice ${invoice.invoiceno} created`);
  console.log(`Payment link: ${invoice.paymentlink.shorturl}`);

  return invoice;
}

// Usage
const items = [
  { itemid: "product_123", name: "Consulting", quantity: 10, rate: 5000 },
];

const invoice = await createAndSendInvoice(
  "customer_456",
  items,
  new Date("2024-02-28")
);

Check Overdue Invoices

javascript
async function getOverdueInvoices() {
  const invoices = await cashfin.invoices.list({
    status: "overdue",
    limit: 100,
  });

  console.log(`Found ${invoices.pagination.total} overdue invoices`);

  for (const invoice of invoices.data) {
    console.log(`${invoice.invoiceno}: KES ${invoice.balance} due`);
  }

  return invoices.data;
}

Update Invoice Status After Payment

javascript
async function markInvoiceAsPaid(invoiceId, paymentNote) {
  const updated = await cashfin.invoices.update(invoiceId, {
    status: "paid",
    description: paymentNote,
  });

  console.log(`Invoice ${updated.invoiceno} marked as paid`);
  return updated;
}

// Usage after receiving payment webhook
markInvoiceAsPaid("invoice_789", "Paid via M-Pesa on 2024-01-20");

Webhooks

Receive notifications when invoice events occur:

EventDescription
invoice.createdNew invoice created
invoice.updatedInvoice details updated
invoice.paidInvoice fully paid
invoice.partially_paidPartial payment received
invoice.overdueInvoice past due date

Webhook Payload Example

json
{
  "event": "invoice.paid",
  "timestamp": "2024-01-20T14:30:00Z",
  "data": {
    "_id": "507f1f77bcf86cd799439020",
    "invoiceno": "INV-2024-001",
    "status": "paid",
    "balance": 0,
    "customer": {
      "_id": "507f1f77bcf86cd799439011",
      "name": "John Doe"
    }
  }
}

See Webhooks Guide for setup instructions.


Best Practices

1. Always Validate Customer First

Ensure the customer exists before creating an invoice:

javascript
const customer = await cashfin.customers.get(customerId);
if (!customer) {
  // Create customer first
  const newCustomer = await cashfin.customers.create({...});
  customerId = newCustomer.id;
}

2. Use Descriptive Titles

Include relevant information in the invoice title:

javascript
const invoice = await cashfin.invoices.create({
  title: `${projectName} - ${month} ${year}`,
  // ...
});

3. Set Reasonable Due Dates

Consider your payment terms when setting due dates:

javascript
// Net 30 payment terms
const dueDate = new Date();
dueDate.setDate(dueDate.getDate() + 30);

4. Handle Partial Payments

Track partial payments by checking the balance:

javascript
if (invoice.status === "partially_paid") {
  const amountPaid = invoice.subtotal - invoice.balance;
  console.log(`Received partial payment of KES ${amountPaid}`);
}

Cashfin Business API Documentation