PHPackages                             trackstone/immo-data-php-sdk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. trackstone/immo-data-php-sdk

ActiveLibrary[API Development](/categories/api)

trackstone/immo-data-php-sdk
============================

PHP SDK for the Immo Data French real estate API

v1.2.0(2w ago)01521MITPHPPHP ^8.3CI passing

Since Feb 24Pushed 2w agoCompare

[ Source](https://github.com/trackstone/immo-data-php-sdk)[ Packagist](https://packagist.org/packages/trackstone/immo-data-php-sdk)[ Docs](https://github.com/trackstone/immo-data-php-sdk)[ RSS](/packages/trackstone-immo-data-php-sdk/feed)WikiDiscussions 1.x Synced today

READMEChangelog (3)Dependencies (9)Versions (5)Used By (1)

Immo Data PHP SDK
=================

[](#immo-data-php-sdk)

[![Tests](https://github.com/trackstone/immo-data-php-sdk/actions/workflows/tests.yml/badge.svg)](https://github.com/trackstone/immo-data-php-sdk/actions/workflows/tests.yml)

A PHP SDK for the [Immo Data API](https://immo-data.fr) — French real estate data including property valuation, geocoding, geographic boundaries, and market prices.

Requirements
------------

[](#requirements)

- PHP 8.3+
- Guzzle 7.5+

Installation
------------

[](#installation)

```
composer require trackstone/immo-data-php-sdk
```

Quick Start
-----------

[](#quick-start)

```
use ImmoData\ImmoDataClient;
use ImmoData\Enums\RealtyType;
use ImmoData\Requests\ValuationRequest;

$client = new ImmoDataClient(apiKey: 'your-api-key');

$request = new ValuationRequest(
    longitude: 2.3488,
    latitude: 48.8534,
    realtyType: RealtyType::Apartment,
    nbRooms: 3,
    livingArea: 65.0,
);

$result = $client->valuation()->estimate($request);

echo $result->mainValuation; // 485000.0
echo $result->confidence;    // 4
```

Configuration
-------------

[](#configuration)

```
use ImmoData\ImmoDataClient;

// Default (production)
$client = new ImmoDataClient(apiKey: 'your-api-key');

// Custom base URL (staging, etc.)
$client = new ImmoDataClient(
    apiKey: 'your-api-key',
    baseUrl: 'https://staging-api.immo-data.fr',
);

// Custom HTTP client (for testing or custom transport)
$client = new ImmoDataClient(
    apiKey: 'your-api-key',
    httpClient: new YourCustomHttpClient(),
);
```

Resources
---------

[](#resources)

The client exposes the following resources:

ResourceMethodDescription`valuation()``estimate()`Property price estimation`geocode()``search()`Location search / autocomplete`geo()``region()`, `department()`, `city()`, `district()`, `subdistrict()`Geographic data and boundaries`market()``priceHistory()`, `currentPrice()`, `saleDurationHistory()`, `currentSaleDuration()`Market price and sale-duration data`transactions()``search()`Real estate transactions (DVF)`dpe()``search()`, `get()`Energy Performance Diagnostics (DPE)---

### Valuation

[](#valuation)

Estimate the price of a property based on its characteristics.

```
use ImmoData\Enums\{RealtyType, Condition, Dpe};
use ImmoData\Requests\ValuationRequest;

$request = new ValuationRequest(
    longitude: 2.3488,
    latitude: 48.8534,
    realtyType: RealtyType::Apartment,
    nbRooms: 3,
    livingArea: 65.0,
    condition: Condition::Excellent,
    bathrooms: 1,
    constructionYear: 1990,
    dpe: Dpe::C,
    floor: 4,
    level: 6,
    elevator: true,
    cellar: true,
    parking: true,
);

$result = $client->valuation()->estimate($request);

$result->mainValuation;  // float — estimated price
$result->upperValuation; // float — upper bound
$result->lowerValuation; // float — lower bound
$result->confidence;     // int   — confidence score (0-5)
```

**Required parameters:** `longitude`, `latitude`, `realtyType`, `nbRooms`, `livingArea`

**Optional parameters:**

ParameterTypeDescription`condition``?Condition`Property condition (-1 = to renovate, 0 = standard, 1 = excellent)`landArea``?float`Land area in m²`bathrooms``?int`Number of bathrooms`constructionYear``?int`Year of construction`dpe``?Dpe`Energy performance rating (A-G)`level``?int`Total number of floors in building`floor``?int`Floor the property is on`pool``?bool`Has swimming pool`cellar``?bool`Has cellar`niceView``?bool`Has nice view`parking``?bool`Has parking`elevator``?bool`Has elevator`patio``?bool`Has patio/terrace---

### Geocode

[](#geocode)

Search for locations by name. Returns structured geographic results with bounding boxes and center coordinates.

```
use ImmoData\Enums\GeoLevel;

// Simple search
$results = $client->geocode()->search('Paris');

foreach ($results as $result) {
    echo $result->label;          // "Paris, Ile-de-France"
    echo $result->geoLevel->value; // "city"
    echo $result->inseeCode;      // "75056"
    echo $result->center?->latitude;
    echo $result->center?->longitude;
}

// Filter by geographic level
$results = $client->geocode()->search(
    query: 'Lyon',
    geoLevels: [GeoLevel::City, GeoLevel::District],
    limit: 10,
);
```

**`GeocodeResult` properties:**

PropertyTypeDescription`geoLevel``GeoLevel`Geographic level (region, department, city, district, street, address)`regionName``?string`Region name`regionCode``?string`Region code`departmentName``?string`Department name`departmentCode``?string`Department code`cityName``?string`City name`inseeCode``?string`INSEE code`districtCode``?string`District (grand quartier) code`subdistrictCode``?string`IRIS code`postCode``string[]`Post codes`streetCode``?string`Street code (street/address results)`streetName``?string`Street name (street/address results)`streetType``?string`Street type, e.g. Rue, Avenue (street/address results)`streetNumber``?string`Street number (address results)`streetSuffix``?string`Street number suffix, e.g. bis, ter (address results)`addressId``?string`Unique address identifier (address results)`parcelIds``string[]`Cadastral parcel identifiers (address results)`boundingBox``?BoundingBox`Bounding box coordinates`center``?Coordinates`Center point (longitude, latitude)`label``string`Human-readable label---

### Geographic Data

[](#geographic-data)

Retrieve geographic entities with their GeoJSON boundaries.

```
// Region
$region = $client->geo()->region('11');
echo $region->regionName;  // "Ile-de-France"
$region->boundaries;       // GeoJsonPolygon

// Department
$department = $client->geo()->department('75');
echo $department->departmentName; // "Paris"

// City (by INSEE code)
$city = $client->geo()->city('75056');
echo $city->cityName;       // "Paris"
echo $city->postCode;       // ["75001", "75002", ...]
echo $city->districtCodes;  // ["7501", "7502", ...]

// District
$district = $client->geo()->district('7514');
echo $district->districtName;     // "Observatoire"
echo $district->subdistrictCodes; // ["751401", "751402", ...]

// Subdistrict (IRIS)
$subdistrict = $client->geo()->subdistrict('751104');
echo $subdistrict->subdistrictName;
```

All geographic entities include a `boundaries` property containing a `GeoJsonPolygon` with `type` and `coordinates`.

---

### Market Data

[](#market-data)

Retrieve real estate market data at the department, city, or district level.

```
use ImmoData\Enums\{GeoLevel, RealtyType};

// Price history for Paris apartments
$history = $client->market()->priceHistory(
    code: '75056',
    geoLevel: GeoLevel::City,
    realtyType: RealtyType::Apartment,
    startDate: '2020-01-01',
    endDate: '2024-12-31',
);

echo $history->metric; // "sqm_price"
foreach ($history->data as $point) {
    echo "{$point->period}: {$point->value} EUR/m²";
}

// Current price for a department
$price = $client->market()->currentPrice(
    code: '75',
    geoLevel: GeoLevel::Department,
    realtyType: RealtyType::Apartment,
);

echo $price->value; // 10234.5 (EUR/m², null if no data available)
```

> Market endpoints only support `GeoLevel::Department`, `GeoLevel::City`, and `GeoLevel::District`. Using other levels will throw an `InvalidArgumentException`.

---

### Sale Duration

[](#sale-duration)

Retrieve how long properties take to sell, at the department, city, or district level. Sale duration is aggregated across all property types and is available from January 2022.

```
use ImmoData\Enums\{GeoLevel, DurationUnit};

// History of the average sale duration for a city
$history = $client->market()->saleDurationHistory(
    code: '75114',
    geoLevel: GeoLevel::City,
    startDate: '2022-01',
    endDate: '2024-12',
    unit: DurationUnit::Days,
);

echo $history->unit; // "days"
foreach ($history->data as $point) {
    echo "{$point->period}: {$point->value} days";
}

// Current average sale duration for a department
$current = $client->market()->currentSaleDuration(
    code: '75',
    geoLevel: GeoLevel::Department,
    unit: DurationUnit::Months,
);

echo $current->unit;  // "months"
echo $current->value; // 3.0 (null if no data available)
```

> Sale-duration endpoints accept the same `GeoLevel::Department`, `GeoLevel::City`, and `GeoLevel::District` levels as the price endpoints. Dates use the `YYYY-MM` format. `currentSaleDuration()->value` is `null` when no data is available.

---

### DPE (Energy Performance Diagnostics)

[](#dpe-energy-performance-diagnostics)

Search Energy Performance Diagnostics (DPE). Like transactions, DPE search supports either `code` + `geoLevel` or `latitude` + `longitude` + `radius`, and is paginated with a `searchAfter` cursor.

```
use ImmoData\Enums\{GeoLevel, Dpe, RealtyType, DpeSortBy, SortOrder};
use ImmoData\Requests\DpeRequest;

$result = $client->dpe()->search(new DpeRequest(
    code: '75114',
    geoLevel: GeoLevel::City,
    dpeRating: [Dpe::F, Dpe::G],          // energy label (étiquette énergie)
    gesRating: [Dpe::E, Dpe::F, Dpe::G],  // climate label (étiquette climat)
    realtyType: [RealtyType::Apartment],
    sortBy: DpeSortBy::Date,
    sortOrder: SortOrder::Desc,
    size: 20,
));

echo $result->total;
foreach ($result->data as $dpe) {
    echo $dpe->dpeNumber;       // "2375E1234567A"
    echo $dpe->dpeRating;       // "D"
    echo $dpe->energyConsFinal; // 180.5 (kWh/m²/an)
    echo $dpe->location?->address?->cityName;
    echo $dpe->realty?->realtyType; // "apartment"
}

// Next page
$next = $client->dpe()->search(new DpeRequest(
    code: '75114',
    geoLevel: GeoLevel::City,
    searchAfter: $result->searchAfter,
));

// Retrieve a single DPE by its ADEME number
$dpe = $client->dpe()->get('2375E1234567A');
echo $dpe->dpeRating; // "D"
```

> DPE search accepts `GeoLevel::City`, `GeoLevel::District`, and `GeoLevel::Address`. The `Dpe` enum (A-G) is reused for both `dpeRating` and `gesRating` filters.

---

Enums
-----

[](#enums)

EnumValues`RealtyType``House`, `Apartment``GeoLevel``Region`, `Department`, `City`, `District`, `Street`, `Address``Dpe``A`, `B`, `C`, `D`, `E`, `F`, `G``Condition``ToRenovate` (-1), `Standard` (0), `Excellent` (1)`MarketType``Sales``Interval``Monthly``Metric``SqmPrice``DurationUnit``Days`, `Months``DpeSortBy``Date`, `LivingArea`, `EnergyConsFinal`---

Error Handling
--------------

[](#error-handling)

All API errors throw typed exceptions extending `ImmoDataException`:

```
use ImmoData\Exceptions\{
    ImmoDataException,
    AuthenticationException,
    ValidationException,
    InsufficientCreditsException,
    ForbiddenException,
    NotFoundException,
    RateLimitException,
    ServerException,
};

try {
    $result = $client->valuation()->estimate($request);
} catch (ValidationException $e) {
    // 400 — invalid parameters
    $errors = $e->errors(); // array of validation errors
} catch (AuthenticationException $e) {
    // 401 — invalid or missing API key
} catch (InsufficientCreditsException $e) {
    // 402 — not enough credits
} catch (ForbiddenException $e) {
    // 403 — forbidden
} catch (NotFoundException $e) {
    // 404 — resource not found
} catch (RateLimitException $e) {
    // 429 — too many requests
} catch (ServerException $e) {
    // 500/502 — server error
} catch (ImmoDataException $e) {
    // catch-all for any API error
    $e->getCode();    // HTTP status code
    $e->errorBody;    // raw error response body
}
```

---

Custom HTTP Client
------------------

[](#custom-http-client)

You can provide your own HTTP client for testing or custom transport by implementing `HttpClientInterface`:

```
use ImmoData\HttpClient\HttpClientInterface;

class MockHttpClient implements HttpClientInterface
{
    public function get(string $path, array $query = []): array
    {
        return match ($path) {
            '/v1/valuation' => [
                'mainValuation' => 500000,
                'upperValuation' => 550000,
                'lowerValuation' => 450000,
                'confidence' => 90,
            ],
            default => throw new \RuntimeException("Unexpected path: {$path}"),
        };
    }
}

$client = new ImmoDataClient(
    apiKey: 'test',
    httpClient: new MockHttpClient(),
);
```

---

Code Style
----------

[](#code-style)

This package uses [PHP CS Fixer](https://github.com/PHP-CS-Fixer/PHP-CS-Fixer) with the PER Coding Style preset.

```
# Fix code style
composer cs

# Check without fixing
composer cs:check
```

Testing
-------

[](#testing)

```
composer test
```

License
-------

[](#license)

MIT

###  Health Score

46

—

FairBetter than 92% of packages

Maintenance97

Actively maintained with recent releases

Popularity14

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 94.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~38 days

Total

4

Last Release

16d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/7335fdf3624fa02c2aaa78e9dffebb9494081dfaae9a22c692231e4f4cb1051f?d=identicon)[blackjak231](/maintainers/blackjak231)

---

Top Contributors

[![blackjak231](https://avatars.githubusercontent.com/u/1529214?v=4)](https://github.com/blackjak231 "blackjak231 (16 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (1 commits)")

---

Tags

apifrancereal-estateimmobiliertrackstoneimmo-datavaluation

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/trackstone-immo-data-php-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/trackstone-immo-data-php-sdk/health.svg)](https://phpackages.com/packages/trackstone-immo-data-php-sdk)
```

###  Alternatives

[tencentcloud/tencentcloud-sdk-php

TencentCloudApi php sdk

3741.3M46](/packages/tencentcloud-tencentcloud-sdk-php)[eslazarev/wildberries-sdk

Wildberries OpenAPI clients (generated).

273.0k](/packages/eslazarev-wildberries-sdk)[resend/resend-php

Resend PHP library.

617.2M43](/packages/resend-resend-php)[files.com/files-php-sdk

Files.com PHP SDK

2481.1k](/packages/filescom-files-php-sdk)[checkout/checkout-sdk-php

Checkout.com SDK for PHP

563.6M13](/packages/checkout-checkout-sdk-php)[scriptdevelop/whatsapp-manager

Paquete para manejo de WhatsApp Business API en Laravel

783.8k](/packages/scriptdevelop-whatsapp-manager)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
