urban-brussels / brussels-permits
PHP wrapper for Nova API, using DTO. Nova is a shared IT platform of the Brussels-Capital Region dedicated to the file management of planning permits, land division permits and environmental licences.
Package info
git.urban.brussels/it-public/brussels-permits/
pkg:composer/urban-brussels/brussels-permits
Requires
- php: ^8.2
- ext-intl: *
- ext-simplexml: *
- maennchen/zipstream-php: ^2.1
- symfony/cache: ^7.1|^8.0
- symfony/deprecation-contracts: ^2.5|^3.0
- symfony/http-client: ^6.0|^7.0|^8.0
- symfony/http-foundation: ^5.4|^6.0|^7.0|^8.0
- symfony/translation: ^7.1|^8.0
- symfony/yaml: ^7.1|^8.0
- urban-brussels/wfs-client: ^0.2.0
- wgirhad/geophp: ^3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.64
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.5
- roave/security-advisories: dev-latest
- symfony/contracts: ^3.5
Suggests
- predis/predis: Redis cache for Organization::getInfo() (REDIS_SERVER env var); falls back to the filesystem cache otherwise
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-05 14:57:03 UTC
README
A PHP library to interact with the Urban Brussels Planning Permits WFS API (Nova). This library allows you to query planning permits (PU) and environmental permits (PE), filter them by location, date, or status, and retrieve detailed information.
composer require urban-brussels/brussels-permits
Configuration
If you are using Symfony, you can configure the service in your services.yaml to enable autowiring:
services:
UrbanBrussels\BrusselsPermits\Service\PermitMapper: ~
UrbanBrussels\WfsClient\WfsClient:
arguments:
$wfsUrl: 'https://geoservices-others.irisnet.be/geoserver/Nova/ows'
UrbanBrussels\BrusselsPermits\PermitsClient:
autowire: true
autoconfigure: true
If you are using this library in a standalone PHP project, you need to instantiate the client manually:
use Symfony\Component\HttpClient\HttpClient;
use UrbanBrussels\BrusselsPermits\PermitsClient;
use UrbanBrussels\BrusselsPermits\Service\PermitMapper;
use UrbanBrussels\WfsClient\WfsClient;
$httpClient = HttpClient::create();
$wfsClient = new WfsClient($httpClient, 'https://geoservices-others.irisnet.be/geoserver/Nova/ows');
$mapper = new PermitMapper();
$client = new PermitsClient($wfsClient, $mapper);
Usage
Version 2.0 introduces PermitsClient, a fluent interface for building queries.
Basic Query
To fetch permits, you must first select the type using from() (PermitType::PU for Urban Planning, PermitType::PE for Environmental), apply filters, and finally call get().
use UrbanBrussels\BrusselsPermits\Model\PermitType;
$permits = $client
->from(PermitType::PU)
->filterByReference('04/PFD/169999')
->get();
foreach ($permits as $permit) {
echo $permit->novaReference; // e.g. 04/PFD/169999
echo $permit->address; // e.g. Rue de la Loi 155, 1040 Bruxelles
}
Complementary data (restricted Nova API)
Charges, documents and linked cases come from the authenticated Nova API. Use PermitDetailsLoader:
use UrbanBrussels\BrusselsPermits\Service\NovaConnection;
use UrbanBrussels\BrusselsPermits\Service\PermitDetailsLoader;
use UrbanBrussels\BrusselsPermits\Service\RestrictedData;
$connection = new NovaConnection($endpoint, $consumerKey, $consumerSecret, $jwtKey);
$loader = new PermitDetailsLoader(new RestrictedData($connection));
$documents = $loader->documents($permit);
$charges = $loader->charges($permit);
The Permit::set*() methods are deprecated; see UPGRADE-3.0.md.
Migration from 1.x
WFSQueryService, Query and GeoJsonFetcher are deprecated: use PermitsClient and its fluent filters instead of arrays of conditions.
Nova API (restricted data)
NovaConnection fetches its OAuth token lazily (first request) and renews it before it expires; a 401 triggers one retry with a fresh token. Both NovaConnection and RestrictedData accept an optional Symfony\Contracts\HttpClient\HttpClientInterface (useful for tests, retries or tracing), and every request has a timeout.
Without further configuration, each NovaConnection instance requests its own token. To reuse it across instances (typically across HTTP requests), pass a PSR-6 cache pool as $tokenCache: the token is stored until it expires (minus the renewal margin) and removed when the API answers 401. Only the token is stored, under a key derived from a hash of the credentials and scope; the credentials themselves never are.
$connection = new NovaConnection($endpoint, $consumerKey, $consumerSecret, $jwtKey, tokenCache: $cachePool);
Communication failures are thrown as UrbanBrussels\BrusselsPermits\Exception\NovaApiException (NovaAuthenticationException for token errors); both extend \RuntimeException.