scopemy.city
Citizen observatory
ReportWhatsApp

API and integrations

Published reports are available through a JSON API, through Open311 (compatible with GIS such as ArcGIS or QGIS and with maintenance systems), through webhooks and through an embeddable widget.

Principles

OpenAPI 3.1 specification: openapi.yaml · openapi.json

curl -H 'Accept: application/json' 'https://scopemy.city/api/v1/signalements?statut=resolu&limite=20'

JSON API

GET /api/v1/signalements

Paginated list of published reports

Parameters of GET /api/v1/signalements
ParameterInDescription
bbox queryArea minLng,minLat,maxLng,maxLat (WGS84).
categorie queryOne or more categories (comma-separated codes).
statut querynouveau, en_cours, resolu or rejete (several, comma-separated).
depuis queryCreated on or after this date (YYYY-MM-DD).
jusqua queryCreated up to and including this date (YYYY-MM-DD).
q querySearch in title, address, description, reference and labels.
lang queryLanguage of labels (fr, de, it, en), among the site's languages.
limite queryReports per page (1 to 100, default 50).
curseur queryOpaque cursor of the next page (pagination.suivant).

Response codes: 200, 400, 429

GET /api/v1/signalements/{reference}

One published report, by reference

Parameters of GET /api/v1/signalements/{reference}
ParameterInDescription
reference * pathReference SC-XXXX-XXXX (or legacy FMC-XXXXXX).

Response codes: 200, 404

GET /api/v1/carte

Reports in the visible map area, grouped at low zoom

Parameters of GET /api/v1/carte
ParameterInDescription
bbox * queryDisplayed area minLng,minLat,maxLng,maxLat (WGS84).
zoom queryWeb Mercator zoom level (0 to 22).
categorie queryOne or more categories (comma-separated codes).
statut querynouveau, en_cours, resolu or rejete (several, comma-separated).
depuis queryCreated on or after this date (YYYY-MM-DD).
jusqua queryCreated up to and including this date (YYYY-MM-DD).
q querySearch in title, address, description, reference and labels.

Response codes: 200, 400

Open311 GeoReport v2

JSON format only. Services are the site's categories, requests are published reports; status is open (new, in progress) or closed (resolved, rejected).

GET /open311/v2/discovery.json

Open311 discovery

Response codes: 200

GET /open311/v2/services.json

Services (the site's categories)

Response codes: 200

GET /open311/v2/requests.json

Published requests (Open311 filters)

Parameters of GET /open311/v2/requests.json
ParameterInDescription
service_request_id queryOne or more references, comma-separated.
service_code queryService code (category).
status queryopen (new, in progress) or closed (resolved, rejected).
start_date queryISO 8601 date (day precision).
end_date queryISO 8601 date (day precision, inclusive).
page queryPage (common extension, from 1).
page_size queryPage size (1 to 100, default 50).

Response codes: 200

POST /open311/v2/requests.json

Submit a request (write API key)

Response codes: 201, 400, 401, 403

GET /open311/v2/requests/{id}.json

One published request

Parameters of GET /open311/v2/requests/{id}.json
ParameterInDescription
id * pathReport reference.

Response codes: 200, 404

Open data

GET /donnees/signalements.csv

CSV export of published reports (CC BY 4.0)

Response codes: 200

GET /donnees/signalements.geojson

GeoJSON export of published reports (CC BY 4.0)

Response codes: 200

GET /donnees/statistiques.json

Public statistics (volume, median delays, resolution rate)

Response codes: 200

Webhooks

An authority can subscribe an https address to these events (administration, API page). We send it a JSON POST within 5 minutes; a report that is not yet published only includes its reference, category, statuses, position and dates.

EventDescription
signalement.creeReport created (awaiting moderation)
signalement.publieReport published
signalement.statutStatus changed (data.ancien_statut holds the previous one)
signalement.reponseOfficial response added or changed
signalement.affecteAssigned to a service or an agent (services portal)

Each delivery is signed in the X-Scopemy-Signature header: t=timestamp,v1=HMAC-SHA256 of the text “t.body” with your secret. Verify it in constant time and reject timestamps older than 5 minutes. X-Scopemy-Delivery gives a stable identifier: ignore a delivery you already received.

$corps = file_get_contents('php://input');
[$t, $sig] = sscanf($_SERVER['HTTP_X_SCOPEMY_SIGNATURE'] ?? '', 't=%d,v1=%s');
$attendu = hash_hmac('sha256', $t . '.' . $corps, $secret);
if (!$sig || !hash_equals($attendu, $sig) || abs(time() - $t) > 300) {
    http_response_code(400); exit;
}
$evenement = json_decode($corps, true);   // id, type, tenant, data.signalement
http_response_code(204);

Any 2xx response counts as received. Otherwise we retry up to 8 times, doubling the wait (1 min, 2 min, 4 min…, 6 h at most). Redirects are not followed.

Widget for the municipal website

Paste this code into a page of the municipal website to show the map and the latest reports, in the authority's branding. The site must first be allowed in the administration (API page).

<script src="https://scopemy.city/embed.js" data-vue="carte-liste" data-hauteur="560" async></script>

Options: data-vue (carte-liste, carte or liste), data-hauteur (in pixels, or auto), data-lang (fr, de, it, en). The widget sets no cookies.