apextechnology/tidybill

PHP SDK for the TidyBill invoicing API — create invoices, manage line items, and fetch clients. Works with any PHP project; optional Laravel support via service provider.

Maintainers

Package info

github.com/Apex-Technology-ZA/tidybill-php

pkg:composer/apextechnology/tidybill

Statistics

Installs: 12

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.1 2026-04-20 07:39 UTC

This package is auto-updated.

Last update: 2026-04-20 07:40:05 UTC


README

A framework-agnostic PHP SDK for the TidyBill invoicing API. Provides a typed client with DTOs for creating invoices, managing line items, and fetching clients. Works in any PHP project; Laravel users get an optional service provider via auto-discovery.

Requirements

  • PHP ^8.2
  • ext-json
  • guzzlehttp/guzzle ^7.0

Installation

composer require apextechnology/tidybill

Plain PHP usage

use ApexTechnology\TidyBill\TidyBillClient;

$client = new TidyBillClient(
    token: 'your-api-token',
    companyId: 'your-company-id',
    baseUrl: 'https://tidybill.app', // optional, this is the default
);

You can also pass a custom GuzzleHttp\ClientInterface as the fourth argument for testing or advanced configuration:

use GuzzleHttp\Client;

$client = new TidyBillClient(
    token: 'your-api-token',
    companyId: 'your-company-id',
    httpClient: new Client(['timeout' => 10]),
);

Laravel usage

Laravel's package auto-discovery registers the service provider automatically. Publish the config file:

php artisan vendor:publish --tag=tidybill-config

This creates config/tidybill.php. Set the following environment variables:

TIDYBILL_TOKEN=your-api-token
TIDYBILL_COMPANY_ID=your-company-id
TIDYBILL_BASE_URL=https://tidybill.app

Resolve the client from the container:

use ApexTechnology\TidyBill\TidyBillClient;

$client = app(TidyBillClient::class);

Or inject it via the constructor in any Laravel service or controller.

Usage

Creating an invoice

use ApexTechnology\TidyBill\DTOs\CreateInvoiceData;
use ApexTechnology\TidyBill\DTOs\LineItemData;

$invoice = $client->createInvoice(new CreateInvoiceData(
    clientId: '42',
    issueDate: '2026-05-01',
    currency: 'ZAR',
    notes: 'Net 30',
    lineItems: [
        new LineItemData(description: 'API usage', quantity: 100, unitPrice: 1.50),
        new LineItemData(description: 'Support hours', quantity: 2, unitPrice: 350.00),
    ],
));

echo $invoice->id;     // int
echo $invoice->status; // 'draft'
echo $invoice->total;  // float (in the currency's major unit)

Adding line items to an existing invoice

use ApexTechnology\TidyBill\DTOs\LineItemData;

// Single item
$lineItem = $client->addLineItem(invoiceId: $invoice->id, item: new LineItemData(
    description: 'Extra usage',
    quantity: 50,
    unitPrice: 0.80,
));

// Multiple items (sequential API calls)
$results = $client->addLineItems(invoiceId: $invoice->id, items: [
    new LineItemData(description: 'Item A', quantity: 1, unitPrice: 100.00),
    new LineItemData(description: 'Item B', quantity: 3, unitPrice: 25.00),
]);

Fetching invoices

// All invoices (with optional filters)
$invoices = $client->getInvoices(['status' => 'draft', 'client_id' => '42']);

// Single invoice
$invoice = $client->getInvoice(id: 123);

// Update an invoice
$updated = $client->updateInvoice(id: 123, data: ['notes' => 'Updated terms']);

Managing line items

// Update a line item
$client->updateLineItem(invoiceId: 123, lineItemId: 10, item: new LineItemData(
    description: 'Revised description',
    quantity: 5,
    unitPrice: 2.00,
));

// Delete a line item
$client->deleteLineItem(invoiceId: 123, lineItemId: 10);

Fetching clients

// All clients
$clients = $client->getClients();

// Single client
$clientData = $client->getClient(id: '42');

echo $clientData->name;  // string
echo $clientData->email; // ?string
echo $clientData->id;    // string

Error handling

use ApexTechnology\TidyBill\Exceptions\TidyBillAuthException;
use ApexTechnology\TidyBill\Exceptions\TidyBillNotFoundException;
use ApexTechnology\TidyBill\Exceptions\TidyBillException;

try {
    $invoice = $client->getInvoice(999);
} catch (TidyBillNotFoundException $e) {
    // 404: invoice does not exist
    echo $e->getMessage();
    echo $e->statusCode;
} catch (TidyBillAuthException $e) {
    // 401 / 403: invalid token or insufficient permissions
} catch (TidyBillException $e) {
    // Any other API error (5xx, etc.)
    // $e->responseBody contains the raw response array
}

DTO reference

CreateInvoiceData

Property Type Default Description
clientId string required TidyBill client ID
issueDate string required ISO 8601 date (e.g. 2026-05-01)
currency string 'ZAR' ISO 4217 currency code
notes ?string null Optional invoice notes
lineItems LineItemData[] [] Line items to include on creation

LineItemData

Property Type Description
description string Line item description
quantity int Number of units
unitPrice float Price per unit in the invoice currency (e.g. 1.50 for R1.50)

Unit prices are converted to integer cents before being sent to the API.

InvoiceResult

Property Type Description
id int Invoice ID
clientId string Client ID
status string Invoice status
issueDate string Issue date
currency string Currency code
total float Invoice total
lineItems array Raw line items from the API
raw array Full raw response

LineItemResult

Property Type Description
id int Line item ID
description string Description
quantity int Quantity
unitPrice float Unit price in currency's major unit
total float Line item total

ClientData

Property Type Description
id string Client ID
name string Client name
email ?string Client email
raw array Full raw response

License

MIT