laravel-bir-regon

← Documentation

Data objects

Company, report, service-status, and diagnostics responses are typed objects based on spatie/laravel-data. get() and search() on a singular identifier builder return collections because one identifier can have records in several GUS silos; sole() returns one CompanyData only when exactly one row exists. Data objects can be read through public properties and converted to arrays or JSON.

$array = $company->toArray();
$json = $company->toJson();

CompanyData

Every item returned by a singular or batch search is a CompanyData.

Property Type Description
regon string Primary REGON value
nip ?string Tax identification number
name string Registered entity name
city ?string Address city
postalCode ?string Postal code
street ?string Street name
buildingNumber ?string Building number
apartmentNumber ?string Apartment number
province ?string Voivodeship
district ?string District
commune ?string Commune
type EntityType Strict GUS entity type
regon14 ?string 14-digit REGON only when GUS returned one
nipStatus ?NipStatus Revoked or invalidated NIP status; otherwise null
silo Silo Strict GUS data-silo identifier
activityEndDate ?string Normalized XML Schema xs:date lexical value, optionally with Z or a +/-hh:mm offset
postCity ?string Postal city

Empty optional values returned by GUS are normalized to null. regon14 is not padded, derived from a REGON-9, or copied from another field.

The closed response vocabularies are represented by backed enums:

Enum Cases and protocol values
EntityType LegalUnit (P), NaturalPerson (F), LegalUnitLocalUnit (LP), NaturalPersonLocalUnit (LF)
Silo Ceidg (1), Agriculture (2), Other (3), DeletedBefore20141108 (4), LegalUnits (6)
NipStatus Revoked (Uchylony), Invalidated (Unieważniony)

EntityType provides exhaustive family checks without requiring consumers to repeat enum case lists:

$company->type->isNaturalPersonFamily(); // F and LF
$company->type->isLegalUnitFamily(); // P and LP

NaturalPerson and NaturalPersonLocalUnit belong to the natural-person family. LegalUnit and LegalUnitLocalUnit belong to the legal-unit family, so both helpers include the corresponding local-unit case.

An empty StatusNip becomes null. An undocumented value in one of these closed fields is treated as an invalid GUS response and results in a BirProtocolException; it is not exposed as a free-form string.

activityEndDate follows the complete xs:date lexical form accepted by the GUS schema: YYYY-MM-DD, the same date suffixed with Z, or the same date with a legal +/-hh:mm offset. XML whitespace is collapsed, but a supplied timezone suffix is retained. Impossible dates and invalid offsets invalidate the protocol response.

FullCompanyReportData

Full reports retain the original decoded rows and add a stable typed projection:

$report->basicData; // CompanyData
$report->reportType; // ReportType
$report->reportData; // list<array<string, string>>
$report->normalized; // NormalizedFullReportData

reportData is the forward-compatible source representation. GUS defines its keys and they differ between report types; unknown fields remain available there. normalized maps documented fields into one of five shapes:

Property Type Used for
entity ?EntityDetailsData A single legal entity, natural-person activity, or local unit
localUnits list<EntityDetailsData> Local-unit list reports
pkdActivities list<PkdActivityData> PKD activity reports
partners list<PartnerData> Civil-partnership partner reports
unitType ?EntityType ReportType::UnitType

The nested DTOs group identity, person name, address, contact, legal-form, registry, lifecycle, and activity-kind fields. Known dates become DateTimeImmutable; known values use NipStatus, Silo, EntityType, and ActivityStatus. PkdActivityData::$classification is a nullable string of at most eight characters because the GUS XSD leaves this version identifier open for future classifications; it is deliberately not an enum. Missing components and fields stay null; list reports use empty lists.

ActivityStatus is deliberately conservative. A termination, removal, bankruptcy, not-started marker, or an unresolved suspension produces Inactive. A start or resumption date can establish Active; when a suspension date is present, the resumption must be strictly later. When a partial report contains only identity or historical metadata and no positive lifecycle evidence, the status is Unknown; absence of an end date alone is never treated as proof that an entity is active.

For the natural-person general report, EntityDetailsData::$activityKinds is a nullable NaturalPersonActivityKindsData with four nullable integer counts: ceidgCount, agricultureCount, otherCount, and deletedBefore20141108Count. These fields are counts from xs:int, not booleans; zero remains 0, while an absent value remains null.

$entity = $report->normalized->entity;

$entity?->identity->name;
$entity?->address?->cityName;
$entity?->contact?->website;
$entity?->lifecycle?->startedAt;

foreach ($report->normalized->pkdActivities as $activity) {
    $activity->classification;
    $activity->code;
    $activity->predominant;
}

Use reportData when GUS adds a field that the current typed projection does not yet cover. Do not infer that a missing normalized property means the raw field was absent without inspecting the selected report’s schema.

Empty rows and rows containing only unknown future fields remain unchanged in reportData, but do not create phantom entity, local-unit, PKD, or partner objects in normalized. List projections omit such rows. For report types whose XSD permits only one row, cardinality is checked against the original raw row list before empty or unknown-only rows are omitted; multiple raw rows still raise BirProtocolException.

Untrusted GUS data

Every public string originating at GUS is untrusted. This includes every string in CompanyData, raw reportData, normalized report DTOs, DiagnosticsData::$message, and ServiceStatusData::$message. The mappers validate documented structure and known scalar types, but deliberately do not sanitize text. A DTO is a structural projection, not an HTML/XSS, SQL-injection, URL, email, spreadsheet-injection, or log-forging boundary.

BulkReportData

$report->date; // DateTimeImmutable
$report->reportType; // BulkReportType
$report->reportData; // list<string>

date is the requested registry day normalized to midnight in the Europe/Warsaw time zone. reportData is a list of REGON strings; unlike a full report, a bulk report does not expose arbitrary row keys.

ServiceStatusData

$status->status; // int
$status->message; // string
$status->isAvailable(); // bool

isAvailable() returns true when GUS reports status code 1. The message string remains untrusted GUS content.

DiagnosticsData

$diagnostics->messageCode; // int
$diagnostics->message; // string
$diagnostics->sessionStatus; // int

The diagnostic message remains untrusted GUS content and requires the same output- and log-context handling described above.

Other return values

get() and search() on singular identifier builders, and get() on batch builders, return an Illuminate\Support\Collection<int, CompanyData>. Singular builder sole() instead returns one CompanyData. Plural full reports return an Illuminate\Support\Collection<int, FullCompanyReportData>, the authenticated data-status operation returns a DateTimeImmutable, and logout() returns a boolean. The collections, date, and boolean are not spatie/laravel-data objects.

See Service status and diagnostics for usage examples.