Open Net Worth
Open Net Worth is an open-source personal AI wealth assistant you run yourself: one ledger for your whole financial life, worked by an AI agent you control.
Free, no-account JSON API for PAYE, VAT, WHT, CIT, CGT & 8 more Nigeria tax calculators — the same math TaxLane's calculators use, with worked curl examples.
FinancePHPGitHub @quineworksOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Official PHP SDK for TaxLane's free Nigeria tax calculator API (PAYE, VAT, WHT, CIT, CGT & 9 more). Mirror of quineworks/tax-lane's sdk-php/, published to Packagist as quineworks/taxlane.
Translation pending
Loading the full README.
Read the full README ↗Nigeria PAYE, VAT, WHT, CIT, CGT & 9 more tax calculators, as static PHP method calls — no API key, no Guzzle, no account.
use TaxLane\TaxLane;
TaxLane::calculatePaye(['grossAnnualIncome' => 6_000_000])['data'];
// ['taxableIncome' => 6000000, 'payeTax' => 870000, 'monthlyTax' => 72500, ...]
ext-curl PHP extension, which
ships with essentially every PHP install (shared hosting, Laravel
Forge/Vapor, Docker's official php images). No Guzzle.TaxLane\TaxLane — one camelCase method per
endpoint, each taking the request body as a plain associative array (the
real camelCase JSON keys, no translation layer) so a call can never drift
from the live API's request shape.Every method returns ['data' => ..., 'rateLimit' => ...] — data is the
parsed JSON response as a plain associative array, not a generated class/DTO
(see Response shape below for why), and rateLimit is
the ceiling that request was measured against (see
Rate limits).
composer require quineworks/taxlane
use TaxLane\TaxLane;
$response = TaxLane::calculatePaye([
'grossAnnualIncome' => 6_000_000,
'annualRentPaid' => 1_200_000,
]);
$response['data'];
// ['taxableIncome' => 5760000, 'payeTax' => 826800, 'annualTax' => 826800, 'monthlyTax' => 68900,
// 'reliefs' => [...], 'bandBreakdown' => [...]]
$response['rateLimit'];
// ['limit' => 50, 'remaining' => 49, 'reset' => 1757750400]
Every method throws TaxLane\TaxLaneApiException (a \RuntimeException --
getMessage()/getCode() carry the API's error string/HTTP status) on a
non-200 response, and accepts an optional trailing $baseUrl argument to
point at a local/staging API instead of the production default:
use TaxLane\TaxLane;
use TaxLane\TaxLaneApiException;
try {
TaxLane::calculatePaye(['grossAnnualIncome' => 'not a number'], 'http://localhost:3000');
} catch (TaxLaneApiException $e) {
echo $e->getCode() . ' ' . $e->getMessage(); // 400 "grossAnnualIncome is required and must be a number"
echo $e->getRetryAfter(); // seconds to wait before retrying, only non-null on a 429
}
| Method | Calculates |
|---|---|
calculatePaye | PAYE on an employee's gross annual income |
calculatePayrollBatch | PAYE for up to 1,000 employees in one call |
calculateVat | VAT on an amount, inclusive or exclusive |
calculatePresumptive | Presumptive tax on turnover |
calculateDirectAssessment | Direct Assessment tax on turnover + expenses |
calculateCit | Companies Income Tax eligibility + liability |
calculateWht | Withholding tax on a transaction |
calculateEmployerCost | Full employer cost of a salary package |
calculateCgt | Capital Gains Tax on a disposal |
calculateStampDuty | Stamp duty on an instrument |
calculateImportDuty | Import duty + landed cost on a shipment |
calculatePayeuse TaxLane\TaxLane;
TaxLane::calculatePaye(['grossAnnualIncome' => 6_000_000, 'annualRentPaid' => 1_200_000])['data'];
// [
// 'taxableIncome' => 5760000,
// 'payeTax' => 826800,
// 'annualTax' => 826800,
// 'monthlyTax' => 68900,
// 'reliefs' => ['rentRelief' => 240000, 'pensionRelief' => 0, 'nhfRelief' => 0, 'nhisRelief' => 0, 'lifeAssurancePremiumRelief' => 0, 'minimumWageExempt' => false, 'taxableTerminationBenefit' => 0],
// 'bandBreakdown' => [
// ['from' => 800000, 'to' => 3000000, 'rate' => 0.15, 'taxInBand' => 330000],
// ['from' => 3000000, 'to' => 5760000, 'rate' => 0.18, 'taxInBand' => 496800],
// ],
// ]
Only grossAnnualIncome is required — every other field defaults to 0.
calculatePayrollBatchuse TaxLane\TaxLane;
TaxLane::calculatePayrollBatch([
'employees' => [
['grossAnnualIncome' => 6_000_000],
['grossAnnualIncome' => 900_000, 'annualRentPaid' => 400_000],
],
])['data'];
// ['results' => [['taxableIncome' => 6000000, ...], ['taxableIncome' => 820000, ...]]]
Calculates PAYE for up to 1,000 employees in one request — results[i] is
exactly what calculatePaye($employees[i]) would return, in the same
order. An invalid item throws with an employees[i].-prefixed message;
there's no partial-success mode.
calculateVatTaxLane::calculateVat(['amount' => 100_000, 'mode' => 'exclusive'])['data'];
// ['net' => 100000, 'vat' => 7500, 'gross' => 107500]
calculatePresumptiveTaxLane::calculatePresumptive(['turnover' => 20_000_000])['data'];
// ['turnover' => 20000000, 'taxOwed' => 200000, 'belowFloor' => false, 'monthlySetAside' => 16666.666666666668, 'turnoverToFloor' => 0]
This is the beginning of the README. Read the rest at the original. Read the full README ↗
calculateNhfContribution| NHF contribution on basic salary |
calculatePensionContribution | Pension contribution + balance projection |
calculateCapitalAllowances | Taxable profit from assessable profit, capital allowances & loss relief |