goatandcow7 / pennylane-sdk
Unofficial PHP SDK for the Pennylane API, the French accounting and invoicing platform
Requires
- php: ^8.2
- ext-json: *
- php-http/discovery: ^1.19
- psr/http-client: ^1.0
- psr/http-client-implementation: ^1.0
- psr/http-factory: ^1.0 || ^1.1
- psr/http-factory-implementation: ^1.0
- psr/http-message: ^1.1 || ^2.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.95
- guzzlehttp/guzzle: ^7.9
- guzzlehttp/psr7: ^2.6
- nyholm/psr7: ^1.8
- php-http/mock-client: ^1.6
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^11.5 || ^12.0
Suggests
- guzzlehttp/guzzle: Default PSR-18 client, enables the timeout option and disables redirects safely
README
The unofficial PHP SDK for the Pennylane API, the French accounting and invoicing platform.
Documentation | API coverage: 213/213 operations
- Complete: every operation of the Company API v2 (165) and the Firm API v1 (48), audited against the official OpenAPI specs in CI.
- Typed: readonly response objects with full IDE autocompletion, tolerant to API additions; monetary amounts are strings, never floats.
- Safe for accounting: the API has no idempotency, so POST is never retried after a server error. No duplicate invoices from a network hiccup.
- Rate-limit proof: built-in client-side throttling to the official limits, plus retry-after aware retries on 429.
- Effortless pagination: foreach over a list call, the SDK fetches the pages.
Not affiliated with Pennylane SAS. Unrelated to the PennyLane quantum computing framework. There is a Python sibling SDK with the same design.
Install
composer require goatandcow7/pennylane-sdk
PHP 8.2+. The SDK is PSR-18 based: any HTTP client works, Guzzle is the suggested default (composer require guzzlehttp/guzzle). Allow the php-http/discovery composer plugin when prompted.
Quickstart
Create an API token in Pennylane (Settings > Connectivity > Developers), then:
use Pennylane\Sdk\Pennylane; use Pennylane\Sdk\Filter; $client = new Pennylane(); // reads PENNYLANE_API_TOKEN // List and filter, with transparent pagination foreach ($client->customerInvoices->list( filter: [Filter::gte('date', '2026-01-01')], sort: '-date', ) as $invoice) { echo $invoice->invoiceNumber, ' ', $invoice->currencyAmount, PHP_EOL; } // Create, finalize, send $invoice = $client->customerInvoices->create( date: '2026-07-08', deadline: '2026-08-07', customerId: 123, invoiceLines: [['product_id' => 45, 'quantity' => '2']], ); $client->customerInvoices->finalize($invoice->id); $client->customerInvoices->sendByEmail($invoice->id);
Accounting firms, across the whole portfolio:
use Pennylane\Sdk\PennylaneFirm; $firm = new PennylaneFirm(); // reads PENNYLANE_FIRM_API_TOKEN foreach ($firm->companies->list() as $company) { foreach ($firm->trialBalance->list( $company->id, periodStart: '2026-01-01', periodEnd: '2026-06-30', ) as $row) { // ... } }
French e-invoicing (2026 reform), Pennylane being an accredited Plateforme Agréée:
use Pennylane\Sdk\FileUpload; $client->customerInvoices->sendToPa($invoice->id); // emit through the PA $client->supplierInvoices->importEInvoice(FileUpload::fromPath('factur-x.pdf')); // ingest Factur-X/UBL/CII
Complete API coverage
| API | Operations | Resources |
|---|---|---|
| Company v2 | 165/165 | customer and supplier invoices, quotes, customers, products, billing subscriptions, banking and reconciliation, journals, ledger entries, lettering, trial balance, analytics, FEC/GL/AGL exports, SEPA/GoCardless/Pro mandates, e-invoicing, changelogs, webhooks |
| Firm v1 | 48/48 | client portfolio, accounting, DMS, exports, invoicing (read), banking, analytics, changelogs |
Coverage is not a promise: scripts/check-coverage.php verifies in CI that every operation in the vendored official OpenAPI specs exists in the SDK.
Learn more
- Getting started
- Guides: authentication, pagination and filtering, errors and retries, invoicing lifecycle, e-invoicing 2026, accounting, Firm API, webhooks, OAuth apps
- API reference
- Examples
- Contributing
Using with AI coding assistants
The documentation is indexed on Context7: point your assistant at it and it gets the whole SDK reference with usage rules. The docs are also published as llms.txt / llms-full.txt, and AGENTS.md sums up the ground rules any tool should follow.
License
MIT. Build whatever you want with it.