API Reference for Developers and System Integrators
Version 1.7 | Last updated: July 2026
This document provides a complete reference for integrating with the Metrici PPD (Parking Place Detector) system. The API allows you to query individual parking spaces, monitor occupancy status, manage groups, and retrieve real-time availability counters across locations, cameras, and groups.
Base URL:
http://<server>/api/ppd/
Minimal example — get free spots at a location:
curl "http://<server>/api/ppd/get_counters_by_location.php?id=1&output=json"
Response:
{
"error": false,
"response": {
"total": 50,
"free": 12,
"busy": 38,
"duration": "0.03"
}
}
The PPD API does not require authentication. All endpoints are publicly accessible via HTTP GET.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer | Yes* | Location, camera, group, or space ID depending on endpoint |
camera_id |
integer | No | Camera ID (required only for get_status_of_place.php) |
output |
string | No | Response format: json (default), xml, dump |
ID, Id, id are all valid.
All endpoints return a consistent JSON structure:
{
"error": false,
"response": {
"header": {
"count": 5,
"duration": "0.02"
},
"body": [ ... ]
}
}
| Field | Type | Description |
|---|---|---|
error |
boolean | false on success, true on error |
response.header.count |
integer | Number of items in the response body |
response.header.duration |
string | Server execution time in seconds |
response.body |
array | List of result objects |
Counter endpoints use a flattened response (no body array):
{
"error": false,
"response": {
"total": 50,
"free": 12,
"busy": 38,
"duration": "0.03"
}
}
Set output=xml to receive XML-formatted responses:
<?xml version="1.0"?>
<body>
<item>
<id>1</id>
<name>Main Parking</name>
</item>
</body>
Set output=dump to receive a PHP var_dump() output for debugging:
curl "http://<server>/api/ppd/get_locations_list.php?output=dump"
Get all parking locations that have at least one PPD camera (camera_type_id = 4).
Endpoint:
GET /api/ppd/get_locations_list.php
Parameters: None
Example:
curl "http://<server>/api/ppd/get_locations_list.php?output=json"
Response:
{
"error": false,
"response": {
"header": {
"count": 2,
"duration": "0.01"
},
"body": {
"1": {
"id": 1,
"name": "Main Parking"
},
"2": {
"id": 3,
"name": "Underground Garage"
}
}
}
}
Response fields:
| Field | Type | Description |
|---|---|---|
id |
integer | Location ID |
name |
string | Location name |
Get the location and all its PPD cameras. The response nests cameras inside the location object.
Endpoint:
GET /api/ppd/get_cameras_list.php
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer | Yes | Location ID |
Example:
curl "http://<server>/api/ppd/get_cameras_list.php?id=1&output=json"
Response:
{
"error": false,
"response": {
"header": {
"count": 1,
"duration": "0.02"
},
"body": {
"1": {
"id": 1,
"name": "Main Parking",
"cameras": {
"0": {
"id": 10,
"name": "Camera A - Level 1"
},
"1": {
"id": 11,
"name": "Camera B - Level 2"
}
}
}
}
}
}
Response fields:
| Field | Type | Description |
|---|---|---|
id |
integer | Location ID |
name |
string | Location name |
cameras |
array | List of cameras with id and name |
Get all place groups defined for a location. Groups are logical collections of parking spaces (e.g., "VIP Section", "Electric Vehicle Charging", "Disabled Parking").
Endpoint:
GET /api/ppd/get_groups_list.php
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer | Yes | Location ID |
Example:
curl "http://<server>/api/ppd/get_groups_list.php?id=1&output=json"
Response:
{
"error": false,
"response": {
"header": {
"count": 3,
"duration": "0.01"
},
"body": {
"1": {
"id": 5,
"name": "VIP Section"
},
"2": {
"id": 8,
"name": "EV Charging"
},
"3": {
"id": 12,
"name": "Disabled Parking"
}
}
}
}
Response fields:
| Field | Type | Description |
|---|---|---|
id |
integer | Group ID |
name |
string | Group name |
Get all registered parking spaces for a location, including their current status and coordinates.
Endpoint:
GET /api/ppd/get_places_by_location.php
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer | Yes | Location ID |
Example:
curl "http://<server>/api/ppd/get_places_by_location.php?id=1&output=json"
Response:
{
"error": false,
"response": {
"header": {
"camera_id": 1,
"count": 50,
"duration": "0.04"
},
"body": {
"1": {
"id": 101,
"status": 0,
"changed_at": "2026-07-30 10:15:22",
"camera_id": 10,
"x": 120,
"y": 85
},
"2": {
"id": 102,
"status": 1,
"changed_at": "2026-07-30 10:12:05",
"camera_id": 10,
"x": 145,
"y": 85
}
}
}
}
Response fields:
| Field | Type | Description |
|---|---|---|
id |
integer | Parking space ID (space_id) |
status |
integer | 0 = Free, 1 = Occupied |
changed_at |
string | Timestamp of last status change |
camera_id |
integer | Camera that monitors this space |
x |
integer | X coordinate of space on camera image |
y |
integer | Y coordinate of space on camera image |
Get all registered parking spaces monitored by a specific camera.
Endpoint:
GET /api/ppd/get_places_by_camera.php
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer | Yes | Camera ID |
Example:
curl "http://<server>/api/ppd/get_places_by_camera.php?id=10&output=json"
Response:
{
"error": false,
"response": {
"header": {
"camera_id": 10,
"count": 25,
"duration": "0.02"
},
"body": {
"1": {
"id": 101,
"status": 0,
"changed_at": "2026-07-30 10:15:22",
"x": 120,
"y": 85
},
"2": {
"id": 102,
"status": 1,
"changed_at": "2026-07-30 10:12:05",
"x": 145,
"y": 85
}
}
}
}
Response fields:
| Field | Type | Description |
|---|---|---|
id |
integer | Parking space ID |
status |
integer | 0 = Free, 1 = Occupied |
changed_at |
string | Timestamp of last status change |
x |
integer | X coordinate on camera image |
y |
integer | Y coordinate on camera image |
Get all parking spaces that belong to a specific group.
Endpoint:
GET /api/ppd/get_places_by_group.php
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer | Yes | Group ID |
Example:
curl "http://<server>/api/ppd/get_places_by_group.php?id=5&output=json"
Response:
{
"error": false,
"response": {
"header": {
"group_id": 5,
"count": 10,
"duration": "0.02"
},
"body": {
"1": {
"id": 201,
"status": 0,
"changed_at": "2026-07-30 09:45:10",
"group_id": 5,
"camera_id": 10,
"x": 200,
"y": 150
},
"2": {
"id": 202,
"status": 1,
"changed_at": "2026-07-30 10:01:33",
"group_id": 5,
"camera_id": 10,
"x": 225,
"y": 150
}
}
}
}
Response fields:
| Field | Type | Description |
|---|---|---|
id |
integer | Parking space ID |
status |
integer | 0 = Free, 1 = Occupied |
changed_at |
string | Timestamp of last status change |
group_id |
integer | Group this space belongs to |
camera_id |
integer | Camera that monitors this space |
x |
integer | X coordinate on camera image |
y |
integer | Y coordinate on camera image |
Get the current status of a single parking space. This is the most granular endpoint, useful for checking individual spots.
Endpoint:
GET /api/ppd/get_status_of_place.php
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer | Yes | Parking space ID |
camera_id |
integer | Yes | Camera ID that monitors this space |
Example:
curl "http://<server>/api/ppd/get_status_of_place.php?id=101&camera_id=10&output=json"
Response:
{
"error": false,
"response": {
"space_id": 101,
"camera_id": 10,
"status": 0,
"x": 120,
"y": 85,
"header": {
"duration": "0.01"
}
}
}
Response fields:
| Field | Type | Description |
|---|---|---|
space_id |
integer | Parking space ID |
camera_id |
integer | Camera ID |
status |
integer | 0 = Free, 1 = Occupied |
x |
integer | X coordinate on camera image |
y |
integer | Y coordinate on camera image |
Counter endpoints return aggregate occupancy data: total spaces, free spaces, and occupied spaces.
Get occupancy counters for an entire location (all cameras combined).
Endpoint:
GET /api/ppd/get_counters_by_location.php
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer | Yes | Location ID |
Example:
curl "http://<server>/api/ppd/get_counters_by_location.php?id=1&output=json"
Response:
{
"error": false,
"response": {
"total": 50,
"free": 12,
"busy": 38,
"duration": "0.03"
}
}
Get occupancy counters for a specific camera.
Endpoint:
GET /api/ppd/get_counters_by_camera.php
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer | Yes | Camera ID |
Example:
curl "http://<server>/api/ppd/get_counters_by_camera.php?id=10&output=json"
Response:
{
"error": false,
"response": {
"total": 25,
"free": 8,
"busy": 17,
"duration": "0.02"
}
}
Get occupancy counters for a specific group of spaces.
Endpoint:
GET /api/ppd/get_counters_by_group.php
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer | Yes | Group ID |
Example:
curl "http://<server>/api/ppd/get_counters_by_group.php?id=5&output=json"
Response:
{
"error": false,
"response": {
"total": 10,
"free": 3,
"busy": 7,
"duration": "0.02"
}
}
| Code | Description |
|---|---|
200 |
Success — response body contains error: false |
200 |
Logical error — response body contains error: true |
| — | Server/database error — returns plain text Status:-1 |
On logical errors, the response follows the standard format:
{
"error": true,
"response": {
"message": "Description of the error"
}
}
On database connection or query failures, the server returns plain text:
Status:-1
This indicates a server-side issue (database unreachable, query failure). Implement retry logic with exponential backoff for these cases.
If a required parameter (id, camera_id) is missing, the server returns:
Status:-1
Typical workflow to display parking availability:
1. GET /api/ppd/get_locations_list.php
└──> Get all parking locations
2. GET /api/ppd/get_counters_by_location.php?id=<location_id>
└──> Get free/busy counters for location
3. GET /api/ppd/get_cameras_list.php?id=<location_id>
└──> Get cameras at this location
4. GET /api/ppd/get_places_by_camera.php?id=<camera_id>
└──> Get individual spaces with status + coordinates
5. GET /api/ppd/get_status_of_place.php?id=<space_id>&camera_id=<camera_id>
└──> Check single space status (polling)
For group-based queries:
1. GET /api/ppd/get_groups_list.php?id=<location_id>
└──> Get all groups at this location
2. GET /api/ppd/get_counters_by_group.php?id=<group_id>
└──> Get counters for specific group
3. GET /api/ppd/get_places_by_group.php?id=<group_id>
└──> Get spaces in this group
<?php
$locationId = 1;
$url = "http://<server>/api/ppd/get_counters_by_location.php?id={$locationId}&output=json";
$response = file_get_contents($url);
$data = json_decode($response, true);
if ($data['error'] === false) {
$total = $data['response']['total'];
$free = $data['response']['free'];
$busy = $data['response']['busy'];
$pct = round(($free / $total) * 100, 1);
echo "Parking: {$free}/{$total} free ({$pct}%)\n";
} else {
echo "Error fetching parking data\n";
}
?>
import requests
server = "http://<server>"
location_id = 1
# Get counters
counters = requests.get(f"{server}/api/ppd/get_counters_by_location.php", params={
"id": location_id,
"output": "json"
}).json()
print(f"Free: {counters['response']['free']}, Busy: {counters['response']['busy']}")
# Get all places
places = requests.get(f"{server}/api/ppd/get_places_by_location.php", params={
"id": location_id,
"output": "json"
}).json()
for key, space in places["response"]["body"].items():
status = "FREE" if space["status"] == 0 else "BUSY"
print(f"Space {space['id']}: {status} at ({space['x']}, {space['y']})")
async function checkSpace(spaceId, cameraId) {
const url = `http://<server>/api/ppd/get_status_of_place.php`
+ `?id=${spaceId}&camera_id=${cameraId}&output=json`;
const res = await fetch(url);
const data = await res.json();
if (!data.error) {
const isFree = data.response.status === 0;
console.log(`Space ${spaceId}: ${isFree ? 'FREE' : 'OCCUPIED'}`);
return isFree;
}
throw new Error('Failed to fetch space status');
}
// Poll every 10 seconds
setInterval(() => checkSpace(101, 10), 10000);
# Location availability
curl -s "http://<server>/api/ppd/get_counters_by_location.php?id=1&output=json" | jq .response
# Single space status
curl -s "http://<server>/api/ppd/get_status_of_place.php?id=101&camera_id=10&output=json" | jq .response.status
# All spaces at camera
curl -s "http://<server>/api/ppd/get_places_by_camera.php?id=10&output=json" | jq '.response.body | length'
| Value | Meaning |
|---|---|
0 |
Free — parking space is available |
1 |
Occupied — parking space is taken |
| Endpoint | Parameters | Description |
|---|---|---|
get_locations_list.php |
— | List all parking locations |
get_cameras_list.php |
id (location) |
List cameras at location |
get_groups_list.php |
id (location) |
List groups at location |
get_places_by_location.php |
id (location) |
List all spaces at location |
get_places_by_camera.php |
id (camera) |
List spaces at camera |
get_places_by_group.php |
id (group) |
List spaces in group |
get_status_of_place.php |
id (space), camera_id |
Status of single space |
get_counters_by_location.php |
id (location) |
Counters for location |
get_counters_by_camera.php |
id (camera) |
Counters for camera |
get_counters_by_group.php |
id (group) |
Counters for group |
Location (parking facility)
├── Camera (PPD camera — camera_type_id = 4)
│ └── Place / Space (parking spot)
│ ├── id (space_id)
│ ├── status (0 = free, 1 = busy)
│ ├── changed_at
│ ├── x (coordinate on image)
│ └── y (coordinate on image)
├── Group (logical collection of spaces)
│ └── Place / Space
└── ...