beziworld / laravel-company-data
Polish company data for Laravel: GUS REGON (BIR) lookup, VAT white list (Biała lista) with bank account checks and EU VIES validation.
Requires
- php: ^8.3
- ext-dom: *
- ext-json: *
- ext-libxml: *
- guzzlehttp/guzzle: ^7.8
- illuminate/contracts: ^12.0|^13.0
- illuminate/http: ^12.0|^13.0
- illuminate/support: ^12.0|^13.0
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.18
- orchestra/testbench: ^10.0|^11.0
- pestphp/pest: ^3.7|^4.0
- pestphp/pest-plugin-laravel: ^3.0|^4.0
- phpstan/phpstan-strict-rules: ^2.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-04 16:36:22 UTC
README
Polish and EU company data for Laravel from three official sources:
- GUS REGON (BIR 1.1/1.2): company name, address, type and full reports by NIP, REGON or KRS
- VAT white list (Wykaz podatników VAT): VAT status, registered bank accounts and account checks with a request id as evidence
- VIES: validation of EU VAT numbers
Installation
composer require beziworld/laravel-company-data
php artisan vendor:publish --tag=company-data-config # optional
GUS_API_KEY=your-key # free, request it at regon_bir@stat.gov.pl GUS_SANDBOX=false # true: test database with the public test key VIES_REQUESTER_COUNTRY=PL # optional: get a VIES consultation number VIES_REQUESTER_VAT_NUMBER=PL1234563218
The white list and VIES need no keys. Lookups are cached for 12 hours (the white list allows only 100 searches a day per IP address).
GUS
use Beziworld\CompanyData\Facades\Gus; $company = Gus::findByNip('526-104-08-28'); // or findByRegon(), findByKrs(), findManyByNip([...]) $company->name; // "GŁÓWNY URZĄD STATYSTYCZNY" $company->regon; // "000331501" $company->type; // EntityType::LegalEntity $company->address(); // "ul. Test-Krucza 208, 00-925 Warszawa" $company->isActive(); Gus::fullReport($company); // all registered fields; the report is chosen from the entity type Gus::pkd($company); // PKD codes Gus::dataDate(); // date of the register data
Sessions are opened on demand, cached for 55 minutes and renewed automatically when GUS expires them.
VAT white list
use Beziworld\CompanyData\Facades\WhiteList; $taxpayer = WhiteList::searchNip('5261040828'); // state of the register today $taxpayer = WhiteList::searchNip('5261040828', '2026-10-01'); $taxpayer?->status; // VatStatus::Active / Exempt / NotRegistered $taxpayer?->accountNumbers; // list of 26-digit NRB numbers $taxpayer?->representatives; $check = WhiteList::checkAccount('5261040828', 'PL61 1090 1014 0000 0712 1981 2874'); $check->assigned; // true when the account belongs to an active VAT payer (virtual accounts included) $check->requestId; // "I55y3-996fi98": store it as evidence of the check
Paying an invoice above PLN 15,000 to an account that is not on the white list can make the payer jointly liable
for the supplier's VAT and excludes the expense from tax costs. Store requestId with the payment.
The API moved to wykazpodatnikowvat.mf.gov.pl in October 2026 (the old wl-api.mf.gov.pl stops on 1 December
2026); the package uses the new host by default.
VIES
use Beziworld\CompanyData\Facades\Vies; $result = Vies::check('DE811569869'); // or check('811569869', 'DE') $result->valid; $result->name; // null when the member state does not disclose it $result->requestIdentifier; // consultation number when requester data are configured Vies::isValid('PL5261040828'); Vies::status(); // ['PL' => true, 'DE' => false, ...]
National systems are often temporarily unavailable or rate limited (MS_UNAVAILABLE, MS_MAX_CONCURRENT_REQ).
Such errors are retried and, if they persist, thrown as ViesException with isTemporary() === true. An invalid
number is not an exception: it returns valid === false.
Usage examples
Fill in the company form from NIP
Route::get('/api/company/{nip}', function (string $nip) { $company = Gus::findByNip($nip); abort_if($company === null, 404); return [ 'name' => $company->name, 'street' => $company->streetLine(), 'postal_code' => $company->postalCode, 'city' => $company->postCity ?? $company->city, 'regon' => $company->regon, ]; });
Verify a supplier before paying
public function pay(Invoice $invoice): void { $check = WhiteList::checkAccount($invoice->supplier_nip, $invoice->bank_account); if (! $check->assigned && $invoice->gross >= 15000) { throw new SupplierAccountNotVerified($invoice); } $invoice->payments()->create([ 'amount' => $invoice->gross, 'white_list_request_id' => $check->requestId, ]); }
Reverse charge for EU customers
try { $reverseCharge = Vies::check($order->vat_number)->valid; } catch (ViesException $e) { $reverseCharge = false; // or queue a re-check when $e->isTemporary() }
Combine it with beziworld/laravel-polish-validation to validate the NIP checksum before calling the APIs.
Exceptions
GusException, WhiteListException (errorCode() such as WL-191, isLimitExceeded(), isTemporary()) and
ViesException (errorCode(), isTemporary()), all extending CompanyDataException.
Development
composer install
composer ci # pint --test, phpstan (level 8), pest
Author
Created and maintained by Kamil Ćwiertnia, beziworld.eu.
- E-mail: biuro@beziworld.eu
- Issues: GitHub issues
Need a B2B integration or a custom Laravel project? Get in touch through beziworld.eu.
Other packages by the author
laravel-polish-validation · laravel-polish-calendar · laravel-nbp · laravel-przelewy24 · laravel-tpay · laravel-smsapi · laravel-directadmin
License
MIT. See LICENSE.md. Data sources: Statistics Poland (GUS), Ministry of Finance, European Commission. This package is not affiliated with any of them.